Objects/components to close or delete on the onDestroy callback - android

I am still not clear about this point and I did not find really clear explanations: what are the objects/components that should be closed/deleted on the onDestroy callbacks?
From what I read, there would be at least:
listeners to remove
database handler to close
But are there other things to handle?
Thanks!

There is no reason to explicitly close something only because it's a database handler or a listener. .
You would want to kill the things that you do not need anymore but that can be mistakenly called after onDelete (or onStop) occured.
Those can be: services because thay are likely not to be killed by OS and thus run while no one needs them. Broadcast receivers because they can get a message from the system and try to process it while your activity is already invalid. Handlers because they can receive messages from other part of your app. Listeners and databases connections because other parts of your app can inadvertently use them while the activity that provides them is already in invalid state.
So, it's a matter of logic what to close in onStop / onDestroy and not a matter of classification.

Exactly what you typed. When that callback method occurs then you will want to close any database connections and anything you are listening to, like SMS messages.
You can also delete temp files during that event. Or maybe you want to send an email off as well. It is really whatever you want but the dev docs really recommend that you close DB xnets and Service xnets.
Lazy developers just leave this method empty.

Related

Is System.exit(0) really that dangerous?

An application background service updates sqlite database. Therefore my activities are becoming outdated. Activity intents also contain outdated params so onCreate, onResume will crash the application. An easiest solution is to restart whole application. I don't want to add IFs to all onCreate, onResume methods in all activities to handle one special case.
I noticed that ACRA has following code executed after an exception has been handled.
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(10);
However many people discourage use of System.exit(0). Is System.exit(0) really that dangerous for an Android application data integrity? Of course my code will close the database before existing.
Update:
I known how to use finish(), content providers, send broadcasts, read many answers here on SO, etc. However each of these approaches requires additional thousands lines of code. I implemented solution with System.exit(0) in ten minutes. The restart is so fast that it is indistinguishable from ordinary startActivity action. The db update/restart is done after longer user inactivity so the app is already suspended by the system. My app doesn't require real time syncing. During tests the application behaves correctly. This is quick and dirty solution.
Therefore I asked the question about possible side effects of System.exit(0). Not how I can do the design differently. I know that current design is not perfect.
System.exit(0) is an artifact from Java runtime, it isn't meant for Android. So in any cases using it would be worst solution.
Why don't you use Activity.finish() gracefully?
If you terminate the process you are living in, you'll loose most of the caching and restart time (~resume in the eyes of the user) for it next time will be higher.
Read more in Activity Lifecycle documentation on Android Developers.
Killing the process will not clean up any registered resources from outside the process. BroadcastReceivers, for example. This is a leak and the device will tell you as much.
You really shouldn't be updating the database schema from a background service. Do it when your activities resume.
If you are just updating your data, resuming an activity should validate the data specified by the Intent and tell the user if, for example, Item X is no longer there.
No tool is that dangerous if used carefully and for a specific, well thought off purpose.
However, In your case I do not believe System.exit() is the right way to go. If your application depends on data from a database, create a background service (or a few, depending on what you need) that will inform your application of changes and update the data. It is, in my opinion the right way to handle changes.
As for scenarios when you want to use System.exit() I personally sometimes use it when I can't recover from a critical error and no graceful degradation is possible. In those cases it is better to force all resources associated with your application to cease rather than just leave loose ends tangling around. To clarify, you should always use error handling before doing anything radical. Proper error handling is often the way to go.
But this is a very delicate topic and you are likely to receive quite a few diverging answers.
Therefore my activities are becoming outdated.
Use a ContentProvider and ContentObserver (or the Loader framework), or use a message bus (LocalBroadcastManager, Otto, etc.) to update the activities in situ.
Activity intents also contain outdated params so onCreate, onResume will crash the application
Copy the relevant "params" to data members of the activities. Update those data members as needed (e.g., from the handlers from the message bus-raised events). Hold onto that data as part of your instance state for configuration change (e.g., onSaveInstanceState()). Use this data from onCreate(), onResume(), etc.
An easiest solution is to restart whole application
It is not easiest, if you value your users, as your users will not appreciate your app spontaneously evaporating while they are using it. Do you think that Gmail crashes their own app every time an email comes in?
Next, you will propose writing a Web app that uses some exploit to crash the browser, because you cannot figure out how to update a Web page.
I noticed that ACRA has following code executed after an exception has been handled.
A top-level exception handler is about the only sensible place to have this sort of code, and even there, the objective is for this code to never run (i.e., do not have an unhandled exception).
There's an existing answer HERE that might give you some help as to why people say it's bad to use System.Exit().

(Reflective) Method call delivers same old results until app is force stopped and restarted (...is there something automatically cached somehow?)

I have a strange problem and hope that someone of you has an idea what happens here.
My app structure is as follows:
I have a main service which registers a broadcast receiver and listens to intents like screen on/off etc. So this service runs indefinitely.
When such an intent is received, I start another service which does the action
Inside this action service I launch an AsyncTask to fetch battery related stats via reflection. After the service is done, it calls stopSelf().
So everything works as expected, except that when the battery related infos have been fetched one time, each subsequent call of the AsyncTask/Reflection methods deliver exactly the same result which has been delivered before.
The battery stats have of course been updated in the meantime, but I do not get the new updated numbers, but always the stats from the first method call.
That is until I go to settings and force stop and restart my app, then I get updated battery statistics again, at least one time, because after that I'm stuck with these numbers again.
So my question:
Could it be that the results of the reflection call are automatically cached somewhere and that each subsequent call doesn't really fetch the new data but just delivers some cached results? What else could be the problem?
I'm thankful for any ideas, I you need some code lemme know :)
Ok, I've found a fix to this :))
The library of Better Battery Stats uses the singleton pattern for a needed class.
It also includes an invalidate() function, which sets the singleton instance to null, so that at the next getInstance() it gets reinitialized.
I'm using now invalidate after each statisitics fetch, and now I get the updated statistics on every call. Although I am still not sure why the Singleton pattern seems to be the root of this issue, it should also work with having one initialized singleton instance...
Well, one does not simply have to understand everything ;-)

Is it possible to save to database right before an Android application closes?

In an Android library I'm writing, I have a queue which has elements constantly being enqueued and dequeued. A required specification is that no elements in the queue are lost. So, if the application closes, I have to save the queue somehow.
I have two options:
1) Ideally, I could save the queue into a SQLite database when the application closes. However, I'm not sure how to detect this, or even if it's possible. In this manner, I can reload the queue elements which were never dequeued back into the queue the next time the app opens. If someone could tell me how to detect the application close from a library (not an Activity), it would be very helpful.
2) If that's not possible, I could write the queue straight into the database for every insertion and removal. However, this is terribly inefficient, and is too slow for my library.
What's the best way to handle this problem?
So, if the application closes, I have to save the queue somehow.
Update the persistent store when entries are added to the queue. For example, Square's Tape offers a persistent queue implementation.
However, I'm not sure how to detect this, or even if it's possible.
It is not possible. The closest thing that Android has to "application closes" is when the process is terminated, and you are not notified about this in advance.
However, this is terribly inefficient, and is too slow for my library.
It works for Square. Their app has been downloaded millions of times and has a ~4.5 star rating on the Play Store, and it uses Tape.
Note that AFAIK Tape does not write to SQLite, though.
You can't detect when an Application is closed, however this work should be done in a Service in which you can override the onDestroy() method.
In onPause event, do the following
if (isFinishing()) // This tells you the app is closing.
Only in this case save it.

Finding Caller of ContentResolver.notifyChange

I have an activity for updating a table which holds configuration data for a service. I am using a SimpleCursorLoader and the SupportLoaderManager to update the listview in that Activity. I destroy the loader in In the activity's onDestroy. This may not be relevant, since the issue I'm seeing happens even without visiting this Activity.
I have a service as well, that registers a ContentObserver on the URI to the table that is modified in the Activity above. It reads its configuration, sets itself up and registers a ContentObserver on that table in the Service's onCreate. In the Service's onDestroy, that listener is unregistered.
This is only 1 of a few databases/tables that I have in my system. What I'm seeing is that when I make an update to a completely different table, the ContentObserver on this configuration URI is being triggered. The Authorities are completely different, they interact with different SqlLite databases, they're even running in different processes within the application. I removed all "notifyChange" calls that I could find which would trigger the ContentObservers, yet they still are firing.
My question is, is there any way to find out who is calling the notifyChange that is causing the ContentObserver to fire? Does the system outside of my application have any reason to notify observers of a URI? I'm trying to track it down, but without having any clue where the notify is coming from, I'm running into a wall.
Again, only a few hours away from the answer. I apparently didn't find all of the notifyChange calls in my code. The offender was:
getContentResolver.notifyChange(new Uri.Builder().build(), null);
which was calling notify on a blank Uri. It doesn't appear to be noted in the documentation, but the behavior I saw was that this triggered all of the registered ContentObservers to be fired in my application. I got that line out of there, and now everything is notifying as it should.
The answer to my original question, "Is there a way to find out who called notifyChange on a Uri?," I think the answer is "Look harder for calls to notifyChange in your code. Other than that, you're on your own."

Detect when application is closed

I want to know when the app is closed, because I need to erase a Database when the user shutdown the app, just in the moment when the user close the app is the right moment to erase the SQLite Database, how can I detect this?
This is a flawed design idea, which reflects a misunderstanding of the system - when the process overall dies, it's dead, meaning your code is no longer running.
You can do some tracking and have the last onDestory()'d activity do the cleanup as a courtesy, but don't assume that it will always actually happen (the method is not always called). If having a stale copy is a problem, clean it up on the next run.
That said, you can try using the ndk to provide a handler for process termination signals, but still I wouldn't count on it working in all cases. The limited potential to gain any sound functionality from this would probably not justify the effort unless you are already familiar with the concepts involved.
And do not for a minute mistake cleaning up for a security mechanism, as the file is there while your app is running, and would remain if your app terminated in an unexpected way.
Supposing you don't finish() your main activity, clearing your database inside the onDestroy() method of that activity might be the closest of what you want to accomplish. As has been pointed in the comments, refer to http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle.

Categories

Resources