Callback listener when application is killed from recent applications in android
Asked Answered
B

1

6

Let me come straight to my issue.

There is an old similar question: Continue Service even if application is cleared from Recent app. Please go through the link before going ahead.

I have to save some data to the local database before the application is destroyed completely.

I have following issues with onTaskRemoved() method of the service:

  1. onTaskRemoved() method is not triggered every time the application(and hence the service) is stopped from the recent applications screen.
  2. Even if onTaskRemoved() is called every time, the method is not executed completely. I mean if there are 20 statements in the method, only 5 or 10 statements are executed and the method breaks after that. Like if I have 20 System.out.println() statements than only 5 or 10 or 12(any random number) statement prints and method breaks after that.

So I can rely on the method onTaskRemoved() method for cleaning up resources acquired by the application.

This is a blocking issue for my application release. I have tried every trick. Like having at least one activity in the stack(I am calling it GhostActivity) so that if the application is killed from the recent applications screen, we can do clean up in onDestroyed() method the activity. onDestroyed() is called but it has exact same issues like onTaskRemoved() method.

I am stuck on the issue since weeks and it's very annoying. Please let me know if anyone has any solution.

Backbencher answered 1/9, 2017 at 13:53 Comment(4)
"I have to save some data to the local database before the application is destroyed completely" -- you need to save your data when the data changes. Don't wait until your process is being terminated to try to save it then.Crowther
@Crowther Actually I need to do some more things when the application is killed. I mentioned database task just to make the issue simple. I need to disable hotspot and restore user's WifiConfiguration as we change the WifiConfiguration programmatically. There are some more things to do. So if I will be able to save data to the database, I will be able to do other tasks.Backbencher
"I need to disable hotspot and restore user's WifiConfiguration as we change the WifiConfiguration programmatically" -- then perhaps you should not have changed those things in the first place. There are plenty of ways that your process can be terminated, and many of those will not result in any sort of callback to your app.Crowther
Actually, This is one of the core feature of the application. I know there may be many more cases. I have handled how the application will behave in such corner cases but killing application from recent apps is a conscious decision of the user so it is a special case. It would be very helpful if we can handle this case. I also tried alarm manager which starts a cleanup service but as it is not guaranteed that the onDestroyed method will be fully executed, this also didn't work.Backbencher
B
1

I finally myself got it worked. I used a combination of service and alarm manager. Every-time I want to handle the force close scenario, I start a service in which I run an infinite loop. This loop will iterator every 15 secs. In the loop, I set an alarm 20 secs from the current time. Now if the next iteration of the loop happens the alarm is updated and reset to 20 secs after new current time. In this way, the alarm will trigger only if the service was not destroyed by the user by calling stopService() method.

public class MyIntentService extends IntentService {

    public MyIntentService() {
        super("My IntentService");
    }

    private boolean stopped = false;
    private Thread runningThread;

    private static MyIntentService mInstance;

    @Override
    public void onCreate() {
        super.onCreate();
        mInstance = MyIntentService.this;
    }

    @Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        stopped = false;
        runningThread = Thread.currentThread();

        while(!this.stopped) {  

            Intent intent = new Intent("Your_Custom_Broadcast_Action");

            AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
            PendingIntent broadcastIntent = PendingIntent.getBroadcast(WifiService.this, CLEAN_UP_ALARM_REQUEST_CODE,
                                                intent, PendingIntent.FLAG_UPDATE_CURRENT);

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 20000, broadcastIntent);
            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                alarmManager.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 20000, broadcastIntent);
            } else {
                alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 20000, broadcastIntent);
            }          
            try {
                Thread.sleep(15000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mInstance = null;
        if (runningThread != null) {
            runningThread.interrupt();
        }
    }

    public void stopService() {
        AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        PendingIntent broadcastIntent = PendingIntent.getBroadcast(WifiService.this, CLEAN_UP_ALARM_REQUEST_CODE,
                                              intent, PendingIntent.FLAG_UPDATE_CURRENT);
        alarmManager.cancel(broadcastIntent);

        stopped = true;
        if (runningThread != null)
            runningThread.interrupt();
    }

    public static MyIntentService getActiveInstance() {
        return mInstance;
    }
}
Backbencher answered 8/9, 2017 at 9:48 Comment(1)
Hi, I don't understand why the code works. Can it listen the killing moment? WhyAirburst

© 2022 - 2024 — McMap. All rights reserved.