Alarm Manager and Pending Intent Cancel Not Working - android

I schedule Alarm from Activity like.
private AlarmManager mAlarmManager;
mAlarmManager = (AlarmManager) ACT_ActiveSession.getAppContext()
.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(mContext, LocalNotification.class);
intent.putExtra("alertBody", "");
intent.putExtra(K.SESSIONID, "");
intent.putExtra("TIME", "");
intent.putExtra("BATCHNO","");
intent.putExtra("REQUEST_CODE", "");
PendingIntent pendingIntent = PendingIntent.getBroadcast(
ACT_ActiveSession.getAppContext(), REQUEST_CODE, intent, 0);
mAlarmManager.setExact(AlarmManager.RTC_WAKEUP, finishTime,
pendingIntent);
// alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, finishTime,
// (1 * 1000), pendingIntent);
intent.putExtra("",""); only used for some task on BroadcastReceiver
And Cancel Alarm From Fragment
private AlarmManager mAlarmManager;
mAlarmManager = (AlarmManager) mActivity
.getSystemService(Context.ALARM_SERVICE);
Intent updateServiceIntent = new Intent(mActivity,
ACT_Home.class);
PendingIntent pendingUpdateIntent = PendingIntent.getBroadcast(
mActivity, REQUEST_CODE,
updateServiceIntent, 0);
pendingUpdateIntent.cancel();
// Cancel alarms
if (pendingUpdateIntent != null) {
mAlarmManager.cancel(pendingUpdateIntent);
Log.e("", "alaram canceled ");
} else {
Log.e("", "pendingUpdateIntent is null");
}
But Alarm Manager is not cancelled.
Here i change mActivity = MyActivity's static getApplicationContext(); and also change different Flags and different Context.
Also I refer many answer. But doesn't work any code. Link1 Link2 Link3
please give me solution as soon as possible.
and apologize for my bad English.

You create the alarm using this Intent:
Intent intent = new Intent(mContext, LocalNotification.class);
But you try to cancel it using this Intent:
Intent updateServiceIntent = new Intent(mActivity, ACT_Home.class);
These Intents do not match, so the cancel does nothing. If you want to cancel the alarm you need to use an Intent in the cancel call that matches the Intent you used to schedule the alarm.

Related

Android: Notification cancels it's repeating alarm

I want my notification to cancel it's own repeating alarm. However, I don't know how to pass pendingIntent (to cancel it later) before it is even created.
Alarms sets here:
public class Schedule extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
wakeLock.acquire();
//next is notification code. //
...
//create intent.
Intent notificationIntent = new Intent(context, MainActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(context,
NOTIFY_ID, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
...
////
wakeLock.release();
}
public void setAlarm(Context context) {
...
Intent intent = new Intent(context, Schedule.class);
intent.putExtra("DELAY", delay);
intent.putExtra("NOTIFICATION_ID", id);
intent.putExtra("TITLE_TEXT", titleText);
intent.putExtra("BIG_TEXT", bigText);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, id, intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 1000 * 60 * delay, 1000 * 60 * delay, pendingIntent);
}
}
The key problem is that I want to cancel the repeating alarm on notification click (intent in onRecieve method), but canceling alarms requires pendingIntent, which notification is a part of. Any way to cheat the system?
Use AlarmManager.cancel() to cancel the specific alarm and use same PendingIntent that was used to create the alarm. Of course, you should use same requestCode(NOTIFY_ID) that was used before.
Try this:
Intent intent = new Intent(this, Schedule.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, NOTIFY_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
Add this code portion into your MainActivty's onCreate() method as your notification will intent to MainActivity when click on it from notification panel.
Hope this will help~

Pending intent with different intent but same ID

I have two pending Intent to use with Alarm Manager one is:
Intent i = new Intent(context, TriggerAlarm.class);
PendingIntent pi =PendingIntent.getBroadcast(context,0,i,PendingIntent.FLAG_CANCEL_CURRENT);
and the other is:
Intent i = new Intent(context, TriggerNotification.class);
PendingIntent pi = PendingIntent.getBroadcast(context,0, i,PendingIntent.FLAG_CANCEL_CURRENT);
I use these two in different methods in my application
my question is:
Are these pendingIntents differnt from each other?? because the intents are different but the Ids are same
If I set alarm manager for each of these pending intent do both of them trigger or one replace another?
So the easy way is test it directly by yourself.
I have tested it on my computer and here is what i got:
Are these pendingIntents different from each other?? because the intents are different but the Ids are same
-Yes they are different each other although the Ids are same
If I set alarm manager for each of these pending intent do both of them trigger or one replace another?
-Both of them will be triggered
Here are my code for test, you can copy and try it by yourself
Copy this method to your activity, and call it
private void setAlarmManager() {
Log.v("AlarmManager", "Configuring AlarmManager...");
Intent startIntent1 = new Intent(context, AlarmReceiverFirst.class);
PendingIntent pendingIntent1 = PendingIntent.getBroadcast(context, 0, startIntent1, PendingIntent.FLAG_CANCEL_CURRENT);
Intent startIntent2 = new Intent(context, AlarmReceiverSecond.class);
PendingIntent pendingIntent2 = PendingIntent.getBroadcast(context, 0, startIntent2, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 20);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Log.v("AlarmManager", "Starting AlarmManager for >= KITKAT version");
alarm.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent1);
alarm.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent2);
} else {
Log.v("AlarmManager", "Starting AlarmManager for < KITKAT version");
alarm.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent1);
alarm.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent2);
}
Log.v("AlarmManager", "AlarmManager has been started");
}
Create your first receiver class
public class AlarmReceiverFirst extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.v(this.getClass().getSimpleName(), "first alarm receiver is called");
}
}
Create your second receiver class
public class AlarmReceiverSecond extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.v(this.getClass().getSimpleName(), "second alarm receiver is called");
}
}
Register those receivers to your manifest
<receiver android:name=".AlarmReceiverFirst" />
<receiver android:name=".AlarmReceiverSecond" />
Not to be confused, what you called Id here is called request code. It is used for cancelling the pending intent.
Intents are just the action PendingIntent is bound to execute once it triggers. But this triggering criteria are entirely depending on PendingIntent itself and RequestCode is playing here a pretty good role to uniquely identify, manage and trigger PendingIntent.
Therefore, no matter what the Intent is, if the requestCode is repeated then the latter PendingIntent will trigger. If you need to trigger multiple PendingIntents, the requestCode must be different from each other.
You can have same name of intents but with different ids like following,
Intent i = new Intent(context, TriggerAlarm.class);
PendingIntent pi =PendingIntent.getBroadcast(context,System.currentTimeMillis(),i,PendingIntent.FLAG_CANCEL_CURRENT);
And
Intent i = new Intent(context, TriggerNotification.class);
PendingIntent pi = PendingIntent.getBroadcast(context,System.currentTimeMillis(), i,PendingIntent.FLAG_CANCEL_CURRENT);
This way both the intents would be distinguished differently from each other and will get triggered.You can have any unique id instead of System.currentTimeMillis()

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);

Cancel alarmmanager from broadcast receiver using Pending intent

I have created a BroadCastReceiver which schedules some events using alarm manager.
In the BroadcastReceiver I am using following code to schedule.
Intent localIntent = new Intent("com.test.sample");
PendingIntent pi = PendingIntent.getBroadcast(context, 0,
localIntent, 0);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + (5 * 60 * 1000),
pi);
Here context comes from the onReceive method of the receiver.
I want to cancel this alarm on receive of other broadcast.
I am aware that alarm can be cancelled by alarmManager.cancel(pi);
However if the alarmanager was set from any other activity that how to get hold of PendingIntent to cancel it?
Thanks
You need to create a new PendingIntent with the same id then pass it as argument in cancelAlarm() method like follows:
To create alarm
int alarmId = 0; /* Dynamically assign alarm ids for multiple alarms */
Intent intent = new Intent(context, AlarmReceiver.class); /* your Intent localIntent = new Intent("com.test.sample");*/
intent.putExtra("alarmId", alarmId); /* So we can catch the id on BroadcastReceiver */
PendingIntent alarmIntent;
alarmIntent = PendingIntent.getBroadcast(context,
alarmId, intent,
PendingIntent.FLAG_CANCEL_CURRENT);
To cancel alarm (in BroadcastReceiverwhitin onReceive(Context context, Intent intent)method)
int alarmId = intent.getExtras().getInt("alarmId");
PendingIntent alarmIntent;
alarmIntent = PendingIntent.getBroadcast(this, alarmId,
new Intent(this, AlarmReceiver.class),
PendingIntent.FLAG_CANCEL_CURRENT);
cancelAlarm(alarmIntent);

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);
}

Categories

Resources