I am currently developing an Application for Android. One of the requirements is extensive logging about how the application is used. More specifically there should be logging about when the user closes the app. This logging consists of a server interaction. With respect to that specific requirement I stumbled onto:
Detect Application Exit(1) and Detect application Exit (2)
Both questions have an accepted answer relying on Service#onTaskRemoved(Intent).
In my case however this solution does not seem to work, i.e. AsyncTasks that are started in this method are only occasionally executed. More specifically, the onPreExecute is executed always but the doInBackground is not. I tested this on a Nexus 5 with Android 6 (Marshmallow) installed.
public class SomeService extends Service {
@Override
public IBinder onBind( Intent aIntent ) {
return null;
}
@Override
public void onTaskRemoved(Intent aRootIntent ) {
new DoSomethingTask().executeOnExecutor( Asyntask.THREAD_POOL_EXECUTOR );
}
private static final class DoSomethingTask extends AsyncTask<Void, Void, Void> {
@Override
protected void onPreExecute() {
Log.e( DoSomethingTask.class.getName(), "This is executed always");
}
@Override
protected Void doInBackground( Void... aParams ) {
Log.e( DoSomethingTask.class.getName(), "This appears to be executed only sometimes... ");
// here an actual call to a Rest API should be made to inform the server that the user has closed the application.
}
@Override
protected void onCancelled( Void result ) {
super.onCancelled( result );
Log.e( DoSomethingTask.class.getName(), "Never invoked" );
}
@Override
protected void onCancelled() {
super.onCancelled();
Log.e( DoSomethingTask.class.getName(), "Never invoked" );
}
}
}
Here is an overview of everything I tried in addition to the above code sample:
- I have tried various
onStartCommandoptions (START_STICKY, START_NOT_STICKY, etc.) without success. - I have also tried restarting the service in the
onTaskRemovedmethod and then executing theAsyncTaskin the onStartCommand. - Starting an
IntentServicein theonTaskRemovedmethod (which starts theAsyncTaskin itsonHandleIntentmethod) solves the problem neither. - using a
BroadcastReceiverin combination with a local broadcast (LocalBroadcastManager#sendBroadcast) does also not work (I double checked that the broadcast receiver is effectively registered as receiver for the sent broadcast).
EDIT:
I have also taken a look at the callbacks in the Application class:
- onTerminate : this method is only invoked in emulated environments and hence useless
- onTrimMemory(int) : this method can be used for detecting when the app goes to the background, but it has no distinct case for when the app exits.
I could keep an activity stack (which would be updated in Activity#onPause(), etc.). But this requires quite a lot of work in every single Activity instead of the above Service approach which only involves interference at a single place.