I'm developing an android app using bluetooth communication (using a propetary protocol) and I need to catch the moment when the app is killed.
I wanted to use the "onDestroy()" method but it isn't called every time the app is killed. I noticed that it is called when I press the back button and, only sometimes, when I kill the app from the task manager.
The question is: How can I catch the moment before the app is killed?
Here is the code I tried to use:
@Override
public void onDestroy() {
sendMessage(msg);
Log.d("SampleApp", "destroy");
super.onDestroy();
}
@Override
public void finish(){
sendMessage(msg);
Log.d("SampleApp", "finish");
super.finish();
}
Unfortunately finish() is never called and onDestroy isn't called every time I close the app from the task manager.
How can I handle this?
I just resolved a similar kind of issue.
Here is what you can do if its just about stopping service when application is killed by swiping from Recent app list.
Inside your Manifest file, keep flag
stopWithTask
astrue
for Service. Like:But as you say you want to unregister listeners and stop notification etc, I would suggest this approach:
Inside your Manifest file, keep flag
stopWithTask
asfalse
for Service. Like:Now in your
MyService
service, override methodonTaskRemoved
. (This will be fired only ifstopWithTask
is set tofalse
).Refer this question for more details, which contains other part of code, too.
Hope this helps.
Your application will not receive any additional callbacks if the process it terminated by external means (i.e. killed for memory reasons or the user Force Stops the application). You will have to make do with the callbacks you received when you app went into the background for your application cleanup.
finish()
is only called by the system when the user presses the BACK button from your Activity, although it is often called directly by applications to leave an Activity and return to the previous one. This is not technically a lifecycle callback.onDestroy()
only gets called on an Activity as a result of a call tofinish()
, so mainly only when the user hits the BACK button. When the user hits the HOME button, the foreground Activity only goes throughonPause()
andonStop()
.This means that Android doesn't provide much feedback to an Activity to differentiate a user going Home versus moving to another Activity (from your app or any other); the Activity itself simply knows it's no longer in the foreground. An Android application is more a loose collection of Activities than it is a tightly integrated singular concept (like you may be used to on other platforms) so there are no real system callbacks to know when your application as a whole has been brought forward or moved backward.
Ultimately, I would urge you to reconsider your application architecture if it relies on the knowledge of whether ANY Activity in your application is in the foreground, but depending on your needs, there may be other ways more friendly to the framework to accomplish this. One option is to implement a bound
Service
inside of your application that everyActivity
binds to while active (i.e. betweenonStart()
andonStop()
). What this provides you is the ability to leverage the fact that a boundService
only lives as long as clients are bound to it, so you can monitor theonCreate()
andonDestroy()
methods of the Service to know when the current foreground task is not part of your application.You might also find this article written by Dianne Hackborn to be interesting covering in more detail the Android architecture and how Google thinks it ought to be used.
As stated in the documentation here, there is no guarantee that onDestroy() will ever be called. Instead, use onPause() to do the things you want to do whenever the app moves into the background, and leave only that code in onDestroy() that you want run when your app is killed.
EDIT:
From your comments, it seems that you want to run some code whenever your app goes into the background, but not if it went into the background because you launched an intent. AFAIK, there is no method in Android that handles this by default, but you can use something like this:
Have a boolean like:
Now before using an intent, set the boolean to true. Now in your onPause(), move the code for the intent case into an if block like this one:
Finally, in your onResume(), set the boolean to false again so that it can deal with your app being moved into the background by a non intent means properly.