How to cancel specific Alarm in android - android

In my app, the user can set multiple alarms for the same movie e.g "On release date", "A week before release", "A month before release" and now I'm stuck on cancelling a specific alarm, I know how to cancel an alarm with and movie id, but how to I cancel it with the movie id and the type. do I concatenate both together and pass it as the id to my pending intent?
Code:
public void cancelAlarm(Context context, _Alarm alarm) {
//Log.d(TAG, "{cancelAlarm}");
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
PendingIntent alarmIntent = PendingIntent.getBroadcast(context, (int) alarm.getGameId(), intent, 0);
alarmManager.cancel(alarmIntent);
}
Alarm class has the id of the movie and the type of the alarm

do I concatenate both together and pass it as the id to my pending
intent?
It seems logical.
Also you can use below way to know if your PendingIntent exists.
PendingIntent alarmIntent = PendingIntent.getBroadcast(context, requestCode,
intent, PendingIntent.FLAG_NO_CREATE);
if (broadcast != null) {
alarmManager.cancel(alarmIntent );
}

Related

how to cancel multiple alarm using other activity

Create note Activity from where Alarm trigger! and Alarm delete code in other Activity,it delete only last trigger Alarm means if 3 Alarm are created and I want to delete Alarm 1 it deletes but when the time of Alarm 1 reaches it trigger while it already deleted and it wont trigger other Alarm 2 and 3, on static broadcast id it trigger only last alarm for example alarm 3 trigger delete code in other activity if it delete on using same pending intent in other activity how can i use the pending intent which use trigger alarm in my delete alarm activity
AlarmManager alarmMgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(getApplicationContext(), AlarmReceiver.class);
String alertTitle = mTitleText.getText().toString();
intent.putExtra(getString(R.string.alert_title), alertTitle);
// broadcastCode++;
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), broadcastCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmMgr.set(AlarmManager.RTC_WAKEUP, calender.getTimeInMillis(), pendingIntent);
cv.put(mDbHelper.TIME, timeString);
cv.put(mDbHelper.DATE, dateString);
public void delete(int id)
{
db.delete( DbHelper.TABLE_NAME, DbHelper.C_ID + "="+id, null);
db.close();
Intent intent = new Intent(getBaseContext(), AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getBaseContext(), CreateNote.broadcastCode, intent, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
}
The PendingIntent needs to be created exactly as it was when you started the AlarmManager.
Use PendingIntent.FLAG_UPDATE_CURRENT instead of 0 when creating the PendingIntent to cancel the alarm. FLAG_UPDATE_CURRENT is equal to the constant 134217728, not 0.
Use this code:
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, _id, intent, 0);
AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
Hope this helps.

Android testing Robolectric NullPointerException creating PendingIntent

I'm trying to create a test of a method that clear some data in the database, cancel one existing AlarmManager (clearing the same PendingIntent) and deleting a file in the storage etc.
The test consist basically in three steps:
- Launch a method that create the alarms managers and put data into the database
- Launch the method that clear everything
- All the check
The test is failing when Robolectric try to create the pending intent with a NullPointerException.
#Test
public void testClearExpiredVideoDownloadedContent() {
mDatabase.post_action().addVideo(mVideoSample, StaticDbConfig.TableNames.DOWNLOADED_CONTENT);
//Run the method to create the timer for downloaded content into the database
int numberAlarmCreated = SuperBase.setUpContextExpireAlarm(mContext);
assertEquals("Alarm has not been created", 1, numberAlarmCreated);
//Run method to clear the expired content
mDatabase.delete_action().clearExpiredVideoContent(mContext, mVideoSample);
//ALL THE CHECKS
}
Method setUpContextExpireAlarm is crashing when i use the pending intent:
Intent intent = new Intent(context, ExpiredContentReceiver.class);
intent.putExtra(ExpiredContentReceiver.EXTRA_VIDEO_INFO, video);
PendingIntent alarmIntent = PendingIntent.getBroadcast(context, video.getId(), intent, PendingIntent.FLAG_NO_CREATE);
SimpleDateFormat format = new SimpleDateFormat(StaticAppConfig.MatDateFormat);
Date d = format.parse(video.getExpiryDate());
alarmMgr.setRepeating( //CRASHING HERE BECAUSE alarmIntent is null
AlarmManager.RTC_WAKEUP,
d.getTime(),
AlarmManager.INTERVAL_DAY,
alarmIntent);
EDIT
This is the method that create the alarm manager and pending intent:
public static int setUpContextExpireAlarm(Context context){
AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
ArrayList<VideosV0> videosV0s = new DatabaseHandler(context, null).get_action().getNotExpiredDownloadedContent();
for(VideosV0 video : videosV0s){
try {
Intent intent = new Intent(context, ExpiredContentReceiver.class);
intent.putExtra(ExpiredContentReceiver.EXTRA_VIDEO_INFO, video);
PendingIntent alarmIntent = PendingIntent.getBroadcast(context, video.getId(), intent, PendingIntent.FLAG_NO_CREATE);
SimpleDateFormat format = new SimpleDateFormat(StaticAppConfig.MatDateFormat);
Date d = format.parse(video.getExpiryDate());
alarmMgr.setRepeating(
AlarmManager.RTC_WAKEUP,
d.getTime(),
AlarmManager.INTERVAL_DAY,
alarmIntent);
Logging.i("Setting up the alarm for content ["+video.getTitle()+" ("+video.getId()+")], the alarm will be triggered on ["+video.getExpiryDate()+"("+d.getTime()+")] ");
} catch (ParseException e) {
e.printStackTrace();
}
}
return videosV0s.size();
}
This call:
PendingIntent alarmIntent = PendingIntent.getBroadcast(context,
video.getId(), intent, PendingIntent.FLAG_NO_CREATE);
does not create a PendingIntent. If you specify PendingIntent.FLAG_NO_CREATE then no PendingIntent is created, it will only return one if there is already one there.
If you want to have multiple alarms, you need to make sure that the PendingIntent is unique. Remove the flag PendingIntent.FLAG_NO_CREATE and make sure to use either a unique ACTION on each Intent OR a unique requestCode in the call to PendingIntent.getBroadcast(). This will ensure that it creates a new one every time.

Stop alarmManager from other activity

I am trying to stop the alarmManager in the MainActivity from the onBackPressed() method in the Map activity. I have tried the code below but the alarmManager is not being stoped and still firing. How can I fix it?
Code in the MainActivity:
Intent intent = new Intent(MainActivity.this, GetLLRD.class);
intent.putExtra("json_data", json);
PendingIntent pendingIntent = PendingIntent.getService(
getApplicationContext(), 123, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Calendar cal = Calendar.getInstance();
alarm.setRepeating(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis(), 20 * 1000, pendingIntent);
startService(intent);
Code in the Map Activity:
#Override
public void onBackPressed() {
Intent intent = new Intent(Map.this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getService(
getApplicationContext(), 123, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarm.cancel(pendingIntent);
}
u problem is u use two different classes for intent to create and stop alarm:
Intent intent = new Intent(context,
GetLLRD.class);
Intent intent = new Intent(context,
MainActivity.class);
/** as in source code - new intent constructor */
public Intent(Context packageContext, Class<?> cls) {
mComponent = new ComponentName(packageContext, cls);
}
if u want to check if u got the same pending intent as before you can try to use:
Intent.filterEquals(oherIntent);
to cancel alarm you have two options use flag or use the same intent on alarm:
PendingIntent.FLAG_CANCEL_CURRENT
& i advice to make pending intent as final - example:
/**
* create pending intent
*/
final PendingIntent pIntent(Intent alarmIntent) {
// Create a PendingIntent to be triggered when the alarm goes off
return PendingIntent.getBroadcast(getApplicationContext(), AlarmReceiver.REQUEST_CODE,
alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
}
/**
* cancel alarm
*/
public void cancelAlarm(Intent alarmIntent, Context context) {
try {
AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
/** use flag cancel here */
PendingIntent pIntent = PendingIntent.getService(context, AlarmReceiver.REQUEST_CODE, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);
/** cancel alarm */
alarm.cancel(pIntent);
} catch (Exception e) {
// handle exception here
}
}
why to make pending intent final ?
because to cancel alarm u need:
Create pending intent with the same id and appropriate intent FLAG.
(to get reference to current pending intent)
PendingIntent.getBroadcast(context, REQUEST_CODE, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
Cancel that pending intent.
PendingIntent.cancel();
Cancel the alarm using alarm manager.
AlarmManager.cancel(PendingIntent);
A PendingIntent itself is simply a reference to a token maintained by the system describing the original data used to retrieve it. This means that, even if its owning application's process is killed, the PendingIntent itself will remain usable from other processes that have been given it. If the creating application later re-retrieves the same kind of PendingIntent (same operation, same Intent action, data, categories, and components, and same flags), it will receive a PendingIntent representing the same token if that is still valid, and can thus call cancel() to remove it.
if you are using activity, use
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(),
12345, intent,0);

Canceling an alarm in AlarmManager

In my code, I create an alarm as follows:
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent("mypackage.START_MONITORING_SERVICE");
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
long timeForNextStart = System.currentTimeMillis() + elapsedTime;
am.set(AlarmManager.RTC_WAKEUP, timeForNextStart, pi);
To cancel the alarm I do this:
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent("mypackage.START_MONITORING_SERVICE");
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
am.cancel(pendingIntent);
My question is whether this is the correct way to cancel ALL alarms of the same intent. The docs say:
Remove any alarms with a matching Intent. Any alarm, of any type,
whose Intent matches this one (as defined by filterEquals(Intent)),
will be canceled.
I'm not exactly sure what defines a "matching intent". If I create multiple alarms with the above code and then peform the cancel as shown, will it cancel ALL of the alarms I created?
You should use PendingIntent flag ==> PendingIntent.FLAG_CANCEL_CURRENT fourth parameters create pendingIntent instance method.
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent,PendingIntent.FLAG_CANCEL_CURRENT);
Try this
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent updateServiceIntent = new Intent(context, MyPendingIntentService.class);
PendingIntent pendingUpdateIntent = PendingIntent.getService(context, 0, updateServiceIntent, 0);
// Cancel alarms
try {
alarmManager.cancel(pendingUpdateIntent);
} catch (Exception e) {
Log.e(TAG, "AlarmManager update was not canceled. " + e.toString());
}
My question is whether this is the correct way to cancel ALL alarms of
the same intent?
I dont know if you aware of requestCode should be unique in for each pendingIntent for following syntax
public static PendingIntent getService (Context context, int requestCode, Intent intent, int flags)
I'm not exactly sure what defines a "matching intent".
Each pending intent map with its provided intent to trigger and each request code map with that intent .
We can say it can be same requestcode for two different pendingIntent which ideally having two different intents .
Remember , here if PendingIntent have a same requestCode for a same intent then it can be override or cancel according to int flags
If I create multiple alarms with the above code and then peform the
cancel as shown, will it cancel ALL of the alarms I created?
To create a multiple alarm you have to give a different requestCode with the same intent .
If you want to cancel those created alarm then you have to cancel them according requestCode
For example
To Create :
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
For (int i= 0 ; i <5 ; i++){
PendingIntent contentIntent = PendingIntent.getBroadcast(TaskReminder.this, i,
new Intent(),PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.set(AlarmManager.RTC_WAKEUP, timeForNextStart, contentIntent);
}
To cancel :
For (int i= 0 ; i <5 ; i++){
//Note here ' i ' is the requestCode which map each pendingIntent with there provided intent
PendingIntent contentIntent = PendingIntent.getBroadcast(TaskReminder.this, i,
new Intent(),PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.cancel(contentIntent);
}

Cancelled alarm is shown to be up

I have read questions on stackoverflow on how to check if an alarm exists for a pending intent.
I check if my alarm exists this way:
boolean alarmUp = (PendingIntent.getBroadcast(context, 0,
new Intent("com.my.package.MY_UNIQUE_ACTION"),
PendingIntent.FLAG_NO_CREATE) != null);
I set an alarm and check is it exist and then cancel the alarm. The alarm is actually cancelled but if run the above statement again, it still returns true.
I have registered the broadcast receiver statically in manifest.
My methods to set and cancel alarms are like this:
public static void cancelRecurringAlarm(Context context, String intentAction) {
Logger.mlog(DEBUG_TAG, "cancelRecurringAlarm called with intent " + intentAction);
Intent reminder = new Intent();
reminder.setClass(context, <receiverClassName>);
reminder.setAction(intentAction);
PendingIntent recurringReminder = PendingIntent.getBroadcast(context, 0, reminder, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarms = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarms.cancel(recurringReminder);
}
public static void setRecurringAlarm(String intentAction, Context context, long timeInMs) {
Logger.mlog(DEBUG_TAG, "setRecurringAlarm called with intent " + intentAction);
Intent reminder = new Intent();
reminder.setClass(context, <receiverClassName>);
reminder.setAction(intentAction);
PendingIntent recurringReminder = PendingIntent.getBroadcast(context, 0, reminder, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarms = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarms.setRepeating(AlarmManager.RTC, timeInMs, AlarmManager.INTERVAL_DAY, recurringReminder);
}
You are getting the Boolean value always as true because you are cancelling the alarm not the pending intent.So cancel your pending intent recurringReminder.cancel() in cancelRecurringAlarm(). Then you will get the Boolean value as false after cancelling alarm

Categories

Resources