andumava
andumava

Reputation: 61

Alarm rescheduling - AlarmManager pendingIntent is not null after force kill

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:

Given this behavior, the user must open the app twice before I could perform the needed actions after force kill. My questions are:

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

Answers (1)

David Wasser
David Wasser

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

Related Questions