How does PendingIntent.cancel() affect AlarmManager if there is a pending alarm.
Should I call cancel on both objects(intent and alarmmanager) to cancel an alarm? Can someone explain how they work together.
Thanks in advance.
Registering PendingIntents
PendingIntent instance can be obtained via factory methods PendingIntent.getActivity(), PendingIntent.getService(), PendingIntent.getBroadcast().
However, apart from just obtaining PendingIntent instance, ActivityManager registers the PendingIntent in internal cache/meta data file if it does not exist. In contrary, if it does exist, then previously registered instance is returned.
For instance,
public static PendingIntent getActivity(Context context, int requestCode,
Intent intent, int flags) {
String packageName = context.getPackageName();
String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
context.getContentResolver()) : null;
try {
intent.setAllowFds(false);
IIntentSender target =
ActivityManagerNative.getDefault().getIntentSender(
IActivityManager.INTENT_SENDER_ACTIVITY, packageName,
null, null, requestCode, new Intent[] { intent },
resolvedType != null ? new String[] { resolvedType } : null, flags);
return target != null ? new PendingIntent(target) : null;
} catch (RemoteException e) {
}
return null;
}
As the documentation states:
/**
* Retrieve a PendingIntent that will start a new activity, like calling
* {@link Context#startActivity(Intent) Context.startActivity(Intent)}.
* Note that the activity will be started outside of the context of an
* existing activity, so you must use the {@link Intent#FLAG_ACTIVITY_NEW_TASK
* Intent.FLAG_ACTIVITY_NEW_TASK} launch flag in the Intent.
...
* @return Returns an existing or new PendingIntent matching the given
* parameters. May return null only if {@link #FLAG_NO_CREATE} has been
* supplied.
Cancelling PendingIntent only
Here's how the cancellation looks like:
/**
* Cancel a currently active PendingIntent. Only the original application
* owning an PendingIntent can cancel it.
*/
public void cancel() {
try {
ActivityManagerNative.getDefault().cancelIntentSender(mTarget);
} catch (RemoteException e) {
}
}
The documentation states that the application can cancel the PendingIntent for you. Essentially, it means that ActivityManager attempts to match the PendingIntent and remove the meta data /cache entry on condition that the matching PendingIntent exists.
If you attempt to get the previously cancelled or unregistered PendingIntent with the flag FLAG_NO_CREATE applied, a null is returned then.
Cancelling PendingIntent via AlarmManager
Cancellation via AlarmManager differs obviously because it removes registered PendingIntent in IAlarmManager's cache/meta data files and from what I noticed diving deeper into Android source code there is no cancellation being done via ActivityManager when an alarm is removed.
public void cancel(PendingIntent operation) {
try {
mService.remove(operation); IAlarmManager instance
} catch (RemoteException ex) {
}
}
Conclusion
You must cancel your alarm via AlarmManager once you register it, cancelling PendingIntent itself and the AlarmManager's alarms cancellation process have nothing in common.
Hope, that I clarified your doubts.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With