Webview saving state of page - android

I have a small problem with a webview I'm using. I'm trying to use the webview to allow the user to fill out a registration form. This works fine when the user completes the form in one session but should the user lock their phone, the webview activity is destroyed.
I have two activities in memory, one of which is quite memory intensive. The problem I believe I'm having is that because this other activity requires more memory than the webview, the webview is destroyed.
I'm fine with this to a degree, but I would really like to be able to save the current state of the web page so the user doesn't have to submit all of their details again. Is there anyway I can do this.
Thanks

try it :-
You can use WebView method saveState()/restoreState() and save it to activity onRestore bundle and use saved value in onCreate method if the previous Activity will be destroyed.
You can use similar method which is described here (but used for only configuration change):
http://www.devahead.com/blog/2012/01/preserving-the-state-of-an-android-webview-on-screen-orientation-change/

We have run into a similar issue. We have an activity with a webview.
We want the user to input 3 fields on a form in the web view, then launch a new activity (camera) to take a picture. When we get the picture back, and using javascript we insert the picture into the currently active webview form. It all works great 99.9% of the time. However, in some odd scenarios which are difficult to reproduce, while the camera activity is active, the webview activity behind it gets destoryed. saveState / restoreState only partially restores the webview. The 3 form fields that the user had inputted but not submitted when we launched the camera are now lost. They do not get saved by webview.saveState. Also, some javascript state on the page is lost too.
To work around this we added a javascript method to the page and invoke it from the app on saveInstanceState. Then after we restore the state, we invoke another javascript method on the webview page to put the state back. It is a pain in the but and requires work for each form you need to do that to, but it works.
I hope future versions of Android webview.saveState save it exactly as it was before the activity gets destroyed. Alternatively it would be great if you mark an activity as critical to your app and only allow that activity to be destroyed if your app is not the current app the user is working with.

try WebView.addJavascriptInterface, when Activity.onPause, call javascript method in page by loadUrl("javascript:..."), and in web page, call native method that provided by WebView.addJavascriptInterface to save data. is this what you want?

An activity can be destroyed when back key is pressed; when the screen is rotated (is faster destroy the activity and recreate that resort all the graphic elements); or when is posible that it will not active in a few time (lock the phone, press home key or other application is started).
You need to do that #Ixx suggest in his comment : Android webView saveState
Save the data of your application with something like
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
/// save your things, e.g.
outState.putString("name", name);
}
And recover, it exists, in the method onCreate
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// if it is a new activity
if (savedInstanceState == null) {
// initialize vars, e.g.
name = "Unknown";
}
// if is a call after detroy the activity
else {
// recover vars, e.g.
name = savedInstanceState.getString("name");
}
}

Related

android onDestroy works fine only on vd

Is anyone aware of the reason why my onDestroy method to save a bool inside my shared pref works fine on vd but doesn't always work on real device?
it looks like working when i quit the app and go back further to main screen but not when i quit the app, remain in the app list window and open the app back again.. weird
is there some bug i'm not aware of or may depend on my other classes? if so i can post the code but is very simple, just as said a bool save and a get
edit: if you guys try to create a scrollview in a fragment (frag of a MainActivity), and try to go on edit mode and press back button to quit your app, mess with it a few times and you'll see onDestroy and even onStop won't be called.
Q. So how am I supposed to save my pref before quitting an app in a consistent way? reliable all the times? also for this i'd need an onDestroy alternative not even onStop, cause I need to save pref only before app quit not on activity change, and since onDestroy isn't reliable (from what Android Dev guide says) what should I use??
thanks
WORKAROUND: I placed this in onCreateView()
boolPref = getActivity().getSharedPreferences("pref_bool", Context.MODE_PRIVATE);
firstVisit = boolPref.getBoolean("bool", DEFAULT);
if (firstVisit == false) {
scrollView.setVisibility(View.VISIBLE);
}else{
scrollView.setVisibility(View.INVISIBLE);
}
if (savedInstanceState == null) {
scrollView.setVisibility(View.INVISIBLE);
}
where firstVisit is boolean firstVisit; declared at start.
(this boolean trick was part of a solution from another post, but it didn't work well saved inside onDestroy() or onStop() cause sometimes they don't get called)
then I added this inside my button onClick:
boolPref = getActivity().getSharedPreferences("pref_bool", Context.MODE_PRIVATE);
SharedPreferences.Editor editor_bool = boolPref.edit();
editor_bool.putBoolean("bool", false);
editor_bool.apply();
scrollView.setVisibility(View.VISIBLE);
and it works, what it basically does is: set my scrollview to be hidden everytime my app starts (through savedInstanceState as #bwt suggested below), and remains hidden when i pass to another activity and come back (using bool = true) unless i press the button inside first activity (setting and saving bool == false) so from then on the scrollview is always visible even if i pass to another activity and come back
I think the right moment to save a preference is when it changes, not when the application quits. Specially since Android may choose to simply kill a process (and the included application) without calling any callback. Use apply() instead of commit(), so that the application does not have to wait.
Alternatively you can override onSaveInstanceState(). It is not part of the basic lifecycle but gives you the opportunity to store the current state of your Activity before being destroyed.

Handling application activities if OS kills the app

I have an app up and running in Play store,i have an issue where android OS kills my app.
Scenario/Steps :
1) Open app, move to any screen.
2) Minimise the app by clicking HOME button.
3) Open several other apps.(say 14 to 15 apps).
4) And now launch my app it CRASHES!!!!.
What i have noticed is instead of app starting from Splash screen it starts from where it was left of and since all my data is lost it gives me NULL POINTER EXCEPTIONS.
Ideally my app should start from the Splash Screen since i am loading all my data there and passing it other activities.
How do i check if my app is killed and load from splash screen ?
I have Application class extended as well but i am not sure how to use that.
I think you might be using static variable(s) , just a hunch. Anyway can you try this in your mainActivity onCreate or onResume:
if (isTaskRoot()) {
// This activity is at root of task, so launch main splash screen
} else {
// This activity isn't at root of task, so continue
}
But thats getting away from the real problem i think: instead i'd look into onSaveInstanceState in Activity class:
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the user's current state
savedInstanceState.putString("myStaticVariable", sStaticVariableAreBad);
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}
then in onCreate check if the activity was previously destroyed:
// Check whether we're recreating a previously destroyed instance
if (savedInstanceState != null) {
// Restore value of members from saved state
sStaticVariableAreBad = savedInstanceState.getString("myStaticVariable");
}

How to change profile data through out application, after changing from settings

I am stuck into this problem,please suggest a solution,
In my application user has settings page (activity) from where they can change profile data like name,profile photo etc..,
Now after user updates his information and comes back to home activity there is still old data is showing up, how can I update this information when user comes back to home.
You could override the protected void onResume() method of your Home Activity and fetch the data there (instead of in the onCreate i guess). This way it gets updated everytime you revisit this activity

Android Webviews, saving the state when changing activity?

I have a number of different webviews, all in their own activity.
When a menu item is pressed a new activity loads and so does it's webview.
Now clicking between activities reloads each webview, is there a way so that when changing activities the web page doesn't reload and it remembers where the user was?
Thanks
You can use WebView method saveState()/restoreState() and save it to activity onRestore bundle and use saved value in onCreate method if the previous Activity will be destroyed.
You can use similar method which is described here (but used for only configuration change):
http://www.devahead.com/blog/2012/01/preserving-the-state-of-an-android-webview-on-screen-orientation-change/

How to handle activity coming to foreground again

The books I have are abysmal at explaining how to work with the lifecycle, there's a lot I'm missing that I'm hoping somebody can fill in.
My app structure is that when it's first started, it starts an activity full of legalbabble that the user has to accept. When he says 'ok', I start my main activity and then I call finish like this:
public void onClick(View view) { //as a result of "I accept"
Intent mainIntent = new Intent(mParent, EtMain.class);
startActivity(mainIntent); // Start the main program
finish();
}
Then in EtMain in the onCreate method, I've got some tabs and I instantiate some classes:
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mTabHost = (TabHost)findViewById(android.R.id.tabhost);
SetupTabs.setMyTabs(mTabHost, this);
mComData = new ComFields(this); // Create the objects
mDepWx = new WxFields(this, DepArr.Departure);
mArrWx = new WxFields(this, DepArr.Arrival);
mDepVs = new DepFields(this);
mArrVs = new ArrFields(this);
mTabHost.setOnTabChangedListener(new OnTabChangeListener(){
}
Questions:
The 'finish' in the first fragment should terminate the legalbabble activity so it'll never be restarted, right? And the EtMain one will remain forever (until killed externally), even if my app gets pushed to the background, right?
The way it is now, when EtMain gets pushed and later brought to the foreground (by tapping on the icon), it goes through the legalbabble screen as though it's a complete start - that's what I'd like to prevent - going thru the legalbabble screen again.
It would seem that I'd want to override onRestart in the second code fragment and put something in there to restart the app, right? That's the part I'm unclear about.
My question then is what needs to be done in onRestart. Do I have to recreate all the tabs and data in the tabs and all my object instantiations? Or is the memory state of the app saved someplace and then is restored back to the state that it was in before something else was brought to the foreground in which case not much needs to be done because all the objects and listeners will still be there?
Yes after the first activity has ended you shouldn't have to view that activity again. You could also write to the shared preferences that the user has previously seen legal info.
If you're UI object creation is in the onCreate method, this should only be called once. Pausing or resuming will not call the onCreate method again.
Unless you explicitly remove your objects and tabChangedListeners in the onPause method, you should not have to touch them in the onRestart method.
Correct, the state of the app is saved automatically. You shouldn't have to touch the onRestart method.
Hope this helps!
I think the problem is that the launch activity in your manifest is the legalbabble activity, so when you click on the icon, the system launches another one. A better architecture would be to launch the legalbabble activity it from your EtMain activity in the onCreate method of the latter, using startActivityForResult. From the docs:
As a special case, if you call startActivityForResult() with a requestCode >= 0 during the initial onCreate(Bundle savedInstanceState)/onResume() of your activity, then your window will not be displayed until a result is returned back from the started activity.
When you get the result in onActivityResult, you can call finish() if the legal stuff was declined; otherwise everything will proceed normally.
This avoids the problem that the launch activity defined in your manifest finishes when the legal stuff is accepted.
EtMain will not remain forever, if the user backs out (by pressing the BACK key) the Activity will be finished (onPause, then onStop, then onDestroy will be called).
In general you can ignore onRestore until you are doing something complicated.
Once the user has exited your application and re-enters (or presses the icon on the Homescreen), onCreate (followed by onStart and onResume) will be called for your first activity, so you do not need any logic in onRestart, your code in onCreate will do the setting up for you as it did the first time. Because of this your legal babble will appear again when the user starts the app after exiting unless you store a preference (in SharedPreferences or a database or file) to indicate you have already displayed it - in which case finish it straight away and start the main activity.
onRestart is only called when the application goes from the stopped state (onStop has been called but not onDestroy) to the started state (onStart is called but onResume has not yet).
For saving data - some components save their state automatically (e.g. EditTexts remember the text in them, TabHosts remember the currently selected tab etc). Some components will not. If you wish to save extra data then make use of onSaveInstanceState and onRestoreInstanceState. You should only use these methods to restore the state of your application or temporary data, not important things, e.g. the id of the resource what the user was looking at, what zoom level they were at etc. For things like contacts or actual data you should commit these changes to a database, SharedPreferences or other permanent storage (e.g. file) when onPause is called.
I recommend taking a look at the Android Activity lifecycle if you are confused. Or ask more questions!

Categories

Resources