Android: Notification cancels it's repeating alarm - android

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~

Related

How to know when a day was started in android?

Is there a way to detect when a day was started or date or time changes (not changed by user, it is changed by system). Any BroadCastReciever to do it? I am using service to run it by every hour, But drains battery.
My requirement is to check when the day has started (when time changes to 12 AM) or time changes (hourly) I want to display the notification.
Create alarm set on a specified time say 00 hours in your case, using AlarmManager and BroadcastReceiver. And you will receive a brodcast on every new day.
private void setAlarm(Calendar targetCal){
Intent intent = new Intent(getBaseContext(), AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getBaseContext(), RQS_1, intent, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, targetCal.getTimeInMillis(), pendingIntent);
}
For further reference :
http://android-er.blogspot.in/2012/05/create-alarm-set-on-specified-time.html
or you can use ScheduledExecutorService to schedule and execute a task http://developer.android.com/reference/java/util/concurrent/ScheduledExecutorService.html
This is quite simple to do.
Step 1
Use the AlarmManager to fire up a BroadcastReceiver periodically..
private void showNotification() {
Intent alarmIntent = new Intent(this, NotificationReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 50000, pendingIntent);
}
Step 2
In the onReceive() do the checking when the time is 00 hours of the day, create a notification and show it.
public class NotificationReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Calendar now = GregorianCalendar.getInstance();
// This is where you check when you want to show the notification
if(now.get(Calendar.HOUR_OF_DAY) == 0){
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(context.getResources().getString(R.string.message_box_title))
.setContentText(context.getResources().getString(R.string.message_timesheet_not_up_to_date));
Intent resultIntent = new Intent(context, MainActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(1, mBuilder.build());
}
}
}
Step 3
Do forgot to register the custom BroadcastReceiver is Manifest
<receiver
android:name="com.example.NotificationReceiver"
android:process=":remote" />

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

Alarm + Notification: nothing happens

I am trying to implement an alarm that would display a notification everyday at the same hour of the day.
Here is the function I'm calling in my activity:
private void restartNotify() {
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
// Intent for our BroadcastReceiver
Intent intent = new Intent(this, AlarmReceiver.class);
// PendingIntent for AlarmManager
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT );
// In case we have already set up AlarmManager, we cancel.
am.cancel(pendingIntent);
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+10000, pendingIntent);
}
And here is my broadcast receiver class
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
NotificationManager nm = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(R.drawable.icon_notif, context.getString(R.string.NotificationLaunchMssg), System.currentTimeMillis());
// This is intent we want to launch when user clicks on the notification.
Intent intentTL = new Intent(context, MyClass.class);
notification.setLatestEventInfo(context, context.getString(R.string.NotificationTitle), context.getString(R.string.NotificationBody),
PendingIntent.getActivity(context, 0, intentTL, PendingIntent.FLAG_CANCEL_CURRENT));
nm.notify(1, notification);
//Here we set next notification, in day interval
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+10000, pendingIntent);
}
}
As you can see in this code I am using a test value (+10000 milliseconds) because I am simply trying to trigger the alarm 10 seconds after my app has started. But it doesn't work, nothing is displayed.
I don't know if the alarm has a problem, or the notification, nothing is happening.
Do you have any idea why?
Thanks for your help
EDIT: after adding some test code in AlarmReceiver method, it turns out this code is never run. So I probably don't call it properly, what is wrong?
Do not use this approach try setInexactRepeating(...) or setRepeating(...) instead. Why are u giving extra work to the BroadcastReceiver for setting alarm every time it receives the intent.
here is a little code:
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
0, 10000, pendingIntent);
// The pending intent will the same as yours. 10000 is the
// interval for between consecutive alarms
as azertiti mentioned in comments " By the time it's registered that time will already be in the past." so use 0 or System.currentTimeMillis().

Android : AlarmManager not start

I must create an AlarmManager that repeating every seconds, I use this code
Intent in = new Intent(context,Tempo_Indietro.class);
in.putExtra("id_widget", appWidgetIds[i]);
PendingIntent pi = PendingIntent.getActivity(context, 0, in, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarm = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarm.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000, pi);
but it don't start...why ??
To start a Scheduled Activity: you can use like:
Step1: Setting for AlarmManager
Intent intent =new Intent(context,AlarmReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, in, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
am.setRepeating(AlarmManger.RTC_WAKEUP,System.currentTimeMillis(), 1000, pi);
Step2: creating a BroadcastReceiver
public class AlarmReceiver extends BroadcastReceiver {
//override onReceive(Context, Intent) method
#Override public void onReceive(Context context, Intent intent)
{
//.........
Intent i = new Intent(context,Tempo_Indietro.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
//..........
}
}
Note: Don’t forget to include the newly created activity, receiver in the AndroidManifest.xml file.

Categories

Resources