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. AsyncTask
s 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
onStartCommand
options (START_STICKY, START_NOT_STICKY, etc.) without success. - I have also tried restarting the service in the
onTaskRemoved
method and then executing theAsyncTask
in the onStartCommand. - Starting an
IntentService
in theonTaskRemoved
method (which starts theAsyncTask
in itsonHandleIntent
method) solves the problem neither. - using a
BroadcastReceiver
in 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.