Why onDestroyed() not called after app pushed out from memory? - android

1) Activity is on onStop() state.
Example: overview button tapped.
2) Working with phone till android pushed out app from memory.
Example: gaming
3) Overview tapped and app tapped then crash
Any solution to destroy it when pushed out from memory?

There is no assurance that onDestroy will ever be called. Do not depend on it, it should be used for opportunistic cleanup only. Especially in the case of a crash, it will NOT be called, because the app may not be in a state where its safe to do so.

You can do a couple things. Manage your absolute necessary clean up in the Application file. (low memory) callback can call the same method.
One idea would be to have a baseclass or abstract model where you keep a reference to the the active version in Application class. Then if low memory is called, you can manually call your (selectedActivity.OnDestroy).
It's a work around to make sure that a low memory calls your cleanup. You can also add one for unhandledException listener to make sure a crash can call your cleanup as well. Depends on how important your final cleanup is in the event of app closure.
If the cleanup is too heavy or time intensive, you can simply set a "bad closure" flag in a DB or shared pref that you check on startup and do your cleanup on the next app launch.

Related

What is cleared when a user kills an app (android)?

When a user manually kills an app, what data is cleared?
I have a bit of functionality that only properly clears the data on app kill and reopen, so clearly the system is clearing some data that I am missing.
Basically, I want to know what sort of delete/clear data is called programatically so that I can try and figure out what is being kept around on close/reopen that doesn't stick around for kill/reopen.
EDIT: I am basically trying to find out the difference between finish() of an activity that contains a webview and force-close/reopen
When you force close, the app will be completely removed from the memory. For example, all services will be closed, any static variables that you might be holding, everything will be cleared. However, persistent storage such as SharedPreferences will not be affected. Every value that was committed before the force closure of the app will be remain as they were.
Also, you cannot expect the lifecycle methods to be called on Force Close. So if you're doing anything inside onDestroy of a Service or an Activity, that'll most likely fail since the method is never called.

Guaranteed alternative to onDestroy()?

I'm trying to execute some code whenever my activity is killed, but not when it's simply moved to the background (so just calling it in onPause() isn't a solution), and I understand onDestory() is not guaranteed to be called. I've been searching all over and haven't found a way to do this. How can I go about tackling this problem? Is it possible?
Nothing. You can never be guarantied to be called when an app ends, because it can always be terminated abnormally- it could crash, the battery could be pulled out, etc. onDestroy is the closest you can come. But you should never write a program that requires cleanup at termination time.
I'm not sure, but I suspect you've got a few issues which you've conflated into one large issue;
As I read this question you have 2 or 3 concerns:
1) You want to garuntee something happens when the app exits.
2) You have state you want to maintain during onPause() but not after onDestroy()
3) You presumably have some content which should not persist between application usages.
Some answers:
1) As Gabe points out - there is no guarantee anything will ever be called. I can pop the back off the device and pull out the battery. Your calls aren't going to happen.
2) You might try onDestroyView() for this case. It won't be called in many circumstances in which onPause will be (for example when an alert dialog is shown), but will be called in others (when you replace a fragment with another fragment for example).
3) This issue makes me think you may want to reconsider your method of storing/saving this information. If you don't want it to exist on the system when you app isn't in use, it is best to never write the data to the filesystem. (Due to 1). Other options are keeping it in memory. You could also use shared preferences/preferences mechanism but this will still exist on the filesystem until your app is removed.

Why should Android data be committed/read in onPause() - onResume() rather than in onStop() - onStart()?

The documentation suggests that the data should be committed/read in onPause()/onResume().
Yet when the application is no longer in the foreground, its data structures remain intact, which suggests that one could delay committing/reading data until the application is no longer visible, i.e. in onStop()/onStart(). Particularly since onStop() is guaranteed to be called before onDestroy().
Is it perhaps the case that either approach is suitable? Is the documentation giving here merely a guideline?
Update
Suppose your application needed to save relatively substantial data, say edits to a large image. One would then surely not write/read in onPause()/onResume(), lest the user experience become sluggish. One would in that case choose instead to write/read in onStop()/onStart(). Is that true?
The problem with using onStop is that you have no guarantees on when it will be called since the only sure thing is that it will be called before onDestroy. If you wait until onStop to commit your data it may be to late for another activity to show/use any of those changes. Same thing applies to onStart, your activity may not need to be restarted if it was just in the background so you'll have stale data. Using onResume and onPause guarantees that your data will always be current, commits are made as soon as the activity goes to the background and new data is loaded as soon as it becomes visible.
Yes, it is just a guideline (and generally a good one). It is up to you exactly when you want to commit changes. I personally like to create Store Objects that allow a simplification of Databases or SharedPreferences, and when a change is made, I commit those changes immediately. For simple data storage, this will be quick and invisible to the user. For large data sets, this may take more time, and you may wish to make those writes on a time interval, as well as in onPause.
As for when to read - you can read whenever, but again longer reads will often affect the user experience, unless you have taken care of it in another thread, such as with an AsyncTask.
To Further answer your update:
It depends on the developer, however I would write in onPause() and if necessary, read in a separate thread, probably initialized with onResume(). I may also write data out on a scheduled interval using a Timer thread, depending on how it would affect the user experience for the current session, and if it would be catastrophic for the phone to turn off and lose all data before onPause() is called.
The true answer to this is, onPause is the only method you are guaranteed to get called before Android can destroy your process. If a user leaves your app to take a phone call, and Android decides to close your process, its entirely legal for you to only get an onPause call. If you hadn't saved your state there, when the user hits the back button, you will end up recreating your activity in a different state than the user left it in.

Any downside to saving preferences frequently in Android?

I have a rather small amount of state in my Android app that I wish to ensure is saved persistently. It's tiny, clocking in at about 50 characters.
Looking at the Android Storage Options page, they give a few choices, the simplest which seems to be shared preferences. Now these aren't actually application preferences, more a short indication of where the application is at.
My worry is that preferences are expected to change infrequently and the likely use case may not therefore handle a lot of changes. By a lot, I mean peaking at about once per second, depending on user activity.
So I want to make sure of two things.
The first is that the sample code on that page linked above has the preferences being written out in the onStop method. Are we guaranteed that this will run when the application exits, no matter what?
If so, I can maintain the state in-memory and use it to save persistently, then this frequency-of-updates problem disappears.
Basically, I want to ensure there's no way my application can stop without having saved its state (short of catastrophic failure of course).
Otherwise, I'd rather save this state whenever it changes so as not to lose anything.
Second, and this is important only if I have to save state every time it changes, are there any downsides to saving preferences up to once per second? As mentioned, I'm not sure if it's designed for frequent updates.
If the application exits normally, onStop() is called. If the application is backgrounded (ie with the home button/getting called) onPause() is called, which calls onStop(). If the application exits (ie with the back button), onPause() is called, which calls onStop(), which calles onDestroy(). However, when the application crashes (ie through a nullpointerException, onStop() is not called, the application just crashes).
Personally, I mostly use a settingsContainerObject of some sort, and just write my preferences to the internal storage in the onStop() method. Works pretty well.
In short: yes, onStop() is always called when the application is backgrounded or exit.
You can also stop the application in try/catch blocks, to always save your settings.

Controlling the Application when the Power Button is pressed and returning to the App

I have app that works perfectly fine on my Phone (desire HD). When I press the power button and return to the app the data has not been reset.
A user has sent me a request that when they click the power button (dell streak) and return to the app the data that is being collected is reset.
I am already saving data away in an object if the back button is pressed
How do you go about finding out when the power is pressed to keep the data and what I need call when the user returns to the app
Thanks for your time
Most likely your activity is being killed whilst in the background. I imagine the Dell Streak is more prone to this as its an older device compared to the HD and probably has less RAM, im not sure how much any Dell customization takes up though (if any).
You probably dont want to be listening for the power button press specifically but rather hooking in the appropriate logic to the Activitys lifecycle methods, especially foccusing on the methods that are called when the activity is created and destroyed as opposed to paused and resumed.
What kind of data is being reset? Is this data being obtained remotly? There are a number of ways to combat this problem.
One is to preserve UI state when the Activity goes is destroyed, see onSaveInstanceState(Bundle)
See here regarding some more info regarding persiting data, which coveres Databases and Shared Prefs which are two alternatives to saving application state (or UI state in some circumstances ) to the onSaveInstanceState() method mentioned above. It really depends on what you are doing :)
Also, are there any remote data gathering operations being triggered in the lifecycle methods (like onCreate()) of this activity? There may be a better architecture for your app if so, say where the lifecycle method just triggers a conditional time-based refresh request thats wrapped in a Service (which is also less likely to be killed in the background) that will just update some model data (in mem or database backed) that the UI can be populated from, but has the advantage that its also persisted so that when your acitvity is killed it will be transparent to the user!
Hope this helps.
EDIT: i just thought, if you are saving state when the back button is pressed and using that saved state to reset the UI state when onResume or onStart is called, are you possibly just clearing the state completely if the activity was put into the background (but not killed) from any other action than pressing the back bytton, as your saved state object will be blank / null / contain default values? If so then the above approaches are still relavent
You will probably want to override your activity's onPause() and onResume() methods.

Categories

Resources