Reputation: 61
I'm searching for a way to understand when an app has been somehow force killed, so that I can perform some tasks the next time the user manually opens the app (restart alarms, reschedule jobs, do cleaning etc). To achieve this I've scheduled an AlarmManager far in the future, and every time the app starts I check if the corresponding pending intent exists or not. If it exists, no force kill happened and so I do nothing. If the pending intent is null instead, it means the app was force killed and the alarm was descheduled, so I schedule it again and I execute all the needed tasks. Unfortunately this approach isn't working: if I force kill the app from the device settings, the first time I reopen the app the pending intent is still existing (method isForceStopped() below returns false), but if i exit from the app and I open it again then the pending intent is null (isForceStopped() returns true).
This is the behavior I find:
AlarmManager is scheduled the first time the app starts
I force kill the application in the device settings I start the app again -> pending intent is not null (isForceStopped() returns false)
I close the app and I start it again -> pending intent is null now (isForceStopped() returns true, alarm is rescheduled
From now on, alarm is scheduled and pending intent is not null
Given this behavior, the user must open the app twice before I could perform the needed actions after force kill. My questions are:
Why the pending intent still exists when the app is launched for the first time? Am I missing something in my code?
More in general, are there better ways to achieve what I need (understand that a force kill happened)?
Current code
public class AlarmChecher {
private static final String ACTION_FORCE_STOP = "ACTION_FORCE_STOP";
private Context mContext;
private static final int ALARM_ID = -1;
private static final long TEN_YEARS = TimeUnit.DAYS.toMillis(10 * 365);
public AlarmChecher(Context context) {
mContext = context;
}
public boolean isForceStopped() {
PendingIntent pendingIntent = getPendingIntent(mContext, FLAG_NO_CREATE);
if (pendingIntent == null) {
setAlarmChecher(mContext);
return true;
} else {
return false;
}
}
private Intent getIntent(Context context) {
Intent intent = new Intent();
intent.setComponent(new ComponentName(context, ForceStopRunnable.BroadcastReceiver.class));
intent.setAction(ACTION_FORCE_STOP);
return intent;
}
private PendingIntent getPendingIntent(Context context, int flags) {
Intent intent = getIntent(context);
return PendingIntent.getBroadcast(context, ALARM_ID, intent, flags);
}
private void setAlarmChecher(Context context) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = getPendingIntent(context, FLAG_UPDATE_CURRENT);
long triggerAt = System.currentTimeMillis() + TEN_YEARS;
if (alarmManager != null) {
alarmManager.setExact(RTC_WAKEUP, triggerAt, pendingIntent);
}
}
}
Then in onCreate() method of my activity
AlarmChecher alarmChecher = new AlarmChecher(this);
if (alarmChecher.isForceStopped()) {
//do actions
alarmJobUtils.rescheduleAll();
}
Upvotes: 2
Views: 465
Reputation: 95628
Don't use negative values for ALARM_ID
. There have been many reports of strange behaviour with negative values for the requestCode
.
Upvotes: 0