Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update time for AlarmManager (Android)

I use AlarmManager to display a notification for an event at the event date and time. But how can I update the time the AlarmManager sends the PendingIndent to my app, when an event is updated?

When an event is created the following code is called:

public void setOneTimeAlarm() {
        Intent intent = new Intent(this, TimerReceiver.class);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0,
                intent, PendingIntent.FLAG_ONE_SHOT);

        Calendar c = Calendar.getInstance();
        c.set(Calendar.YEAR, year);
        c.set(Calendar.MONTH, month);
        c.set(Calendar.DAY_OF_MONTH, day-1);
        c.set(Calendar.HOUR_OF_DAY, 18);
        c.set(Calendar.MINUTE, 00);

        long date = c.getTimeInMillis();

        mAlarmManager.set(AlarmManager.RTC_WAKEUP, date, pendingIntent);
    }

The indent called is TimerReciver:

@Override
     public void onReceive(Context context, Intent intent) {
         Log.v("TimerReceiver", "onReceive called!");
         Intent notificationIntent = new Intent(context, ListTests.class);
            PendingIntent contentIntent = PendingIntent.getActivity(context,
                    123, notificationIntent,
                    PendingIntent.FLAG_CANCEL_CURRENT);

            NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

            Resources res = context.getResources();
            NotificationCompat.Builder builder = new NotificationCompat.Builder(context);

            long[] pattern = {0,300};

            builder.setContentIntent(contentIntent)
                        .setSmallIcon(R.drawable.ic_launcher)
                        .setLargeIcon(BitmapFactory.decodeResource(res, R.drawable.ic_launcher))
                        .setTicker(res.getString(R.string.app_name))
                        .setWhen(System.currentTimeMillis())
                        .setAutoCancel(true)
                        .setVibrate(pattern)
                        .setContentTitle(res.getString(R.string.notification_title))
                        .setContentText(res.getString(R.string.notification_text));
            Notification n = builder.build();

            nm.notify(789, n);
     }
like image 844
EirikO Avatar asked May 26 '13 19:05

EirikO


People also ask

Is AlarmManager deprecated?

IntentService + WakefulBroadcastReceiver + AlarmManager are deprecated with API 26 (Android 8.0 Oreo).

How do I stop my Android phone from repeating an alarm?

Open your phone's Clock app . At the bottom, tap Alarm. On the alarm you want, tap the Down arrow . Cancel: To cancel an alarm scheduled to go off in the next 2 hours, tap Dismiss.

How is AlarmManager different from WorkManager?

Alarms only. Unlike WorkManager, AlarmManager wakes a device from Doze mode. It is therefore not efficient in terms of power and resource management. Only use it for precise alarms or notifications such as calendar events — not background work.

In which API level did inexact timing become the default for AlarmManager?

The way that AlarmManager works was changed in API level 19 to help save battery life. It was so that events could be batched. What this means is that set() and setRepeating() will be inexact on API 19+. In API versions before 19, you can just use set, which will schedule an alarm for the exact time.


1 Answers

I found the solution.. I turns out that the second argument to getBroadcast(Context context, int requestCode, Intent intent, int flags) makes the difference, even when the documentation says

requestCode Private request code for the sender (currently not used).

When a request id is used for each event, the alarm is updated and alarms are created for each event.

The reason is that with two different request codes, the filterEquals(Intent) will be false. Documentation of AlarmManager set(...) says:

If the time occurs in the past, the alarm will be triggered immediately. If there is already an alarm for this Intent scheduled (with the equality of two intents being defined by filterEquals(Intent)), then it will be removed and replaced by this one.

I also changed PendingIntent.FLAG_ONE_SHOT to PendingIndent.FLAG_CANCEL_CURRENT.

like image 97
EirikO Avatar answered Nov 14 '22 23:11

EirikO