Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Callback listener when application is killed from recent applications in android

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.

like image 437
Tarun Kumar Avatar asked Nov 08 '22 17:11

Tarun Kumar


1 Answers

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;
    }
}
like image 92
Tarun Kumar Avatar answered Nov 15 '22 08:11

Tarun Kumar