3

My app needs to show notifications to users at certain specified time in the future (maybe months away). In iOS, all I need to do is this:

UILocalNotification* localNotification = [[UILocalNotificationalloc] init]; 
localNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:60];
localNotification.alertBody = @"Your alert message";
localNotification.timeZone = [NSTimeZone defaultTimeZone];
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];

However, in Android, it is much more complicated than I originally expected:

  1. I have to install alarms with Alarm Manager, to start a service at each specified time in future.

  2. These services, in turn, create a notification, and use Notification Manager to push the notification to status bar, etc.

But this solution has problems:

  1. If the device is restarted before the alarm fires, the alarm is lost. I can register for boot-up broadcast like this and re-install the services. However, I really want to avoid installing duplicate alarms for the same event, but it seems there is no way to get currently installed alarms from the Alarm Manager?
  2. The notification is composed at the scheduled time in future (say a month later), not when I set the notification(now). At that time, the required data for the notification may no longer be available. I don't see any way around this, except to store the relevant data, and wait for the alarm to fire.

Is there a pain-free solution to the local notification problem on Android?

Community
  • 1
  • 1
NeoWang
  • 17,361
  • 24
  • 78
  • 126

1 Answers1

6

If the device is restarted before the alarm fires, the alarm is lost. I can register for boot-up broadcast like this and re-install the services. However, I really want to avoid installing duplicate alarms for the same event, but it seems there is no way to get currently installed alarms from the Alarm Manager?

How are you going to get duplicated alarms when the device is restarted? When the device is restarted all alarms are canceled so you would do like you said where you start it again in the BroadcastReceiver when the device boots

The notification is composed at the scheduled time in future (say a month later), not when I set the notification(now). At that time, the required data for the notification may no longer be available. I don't see any way around this, except to store the relevant data, and wait for the alarm to fire.

that is correct you need to store the data that you want to show in the notification, SharedPreferences will probably be the easiest

EDIT:

You do not need to keep a reference to the pending intent all you have to do is create the intent the same way example

when you first created the alarm you used this intent

Intent intent = new Intent(context,MyClass.class);
    //any flags or extras

PendingIntent.getBroadcast(context, 0, intent, 0);

Now you want to cancel that alarm so just create the same intent again, it must be a 1 for 1 of the origional

Intent intent = new Intent(context,MyClass.class);
    //any flags or extras that you previously had

PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);

alarmMgr.cancel(pi);
tyczj
  • 71,600
  • 54
  • 194
  • 296
  • To answer your question: I can use the a service to install all alarms at bootup, but this same service is called when new events are ready (with no reboot), in this case, old events got installed twice. Is there no method like getCurrentAlarms()? The user may need to cancel one alarm set previously, how can he do that? – NeoWang Dec 15 '14 at 18:39
  • 1
    No there is no way to get all the pending intents, Have you looked up how to cancel alarms? If all your alarm creation is done in one spot just cancel any alarm there using the same intent you created it with – tyczj Dec 15 '14 at 18:42
  • I know about cancel(PendingIntent operation) API. But the alarm may need to be cancelled some time after it was set (decide not to take a trip a week after planned), I cannot keep references to the PendingIntents, can I? – NeoWang Dec 15 '14 at 18:53
  • I didn't read the doc closely. The API uses filterEquals (Intent other) to compare, not references. Thanks! – NeoWang Dec 15 '14 at 19:10