5

Since the release of Android Lollipop 5.0 (API21), there is now an API to officially show/hide the alarm icon. There is more information about this here on stackoverflow.

Thanks to it, I managed to now display the alarm icon on 5.0+ Android devices. Unfortunately, I can't dismiss/hide/cancel the icon if the alarm is disabled.

Here is what I'm doing (a mix of several attempts from Stackoverflow and Android stock alarm) :

public static void setNextAlert(final Context context) {

final Alarm alarm = calculateNextAlert(context);

AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(ALARM_ALERT_ACTION);

PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);

int flags = alarm == null ? PendingIntent.FLAG_NO_CREATE : 0;
PendingIntent operation = PendingIntent.getBroadcast(context, 0 /* requestCode */,  intent, flags);


if (alarm != null) 
{
    if(UtilsAlarm.isLollipopOrLater())
    {
        PendingIntent viewIntent = PendingIntent.getActivity(context, alarm.id, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        AlarmManager.AlarmClockInfo info = new AlarmManager.AlarmClockInfo(alarm.time, viewIntent);
        am.setAlarmClock(info, operation);
    }
    else
    {
        if(UtilsAlarm.isKitKatOrLater())
        {
            am.setExact(AlarmManager.RTC_WAKEUP, alarm.time, sender);
        }
        else
        {   
            am.set(AlarmManager.RTC_WAKEUP, alarm.time, sender);
        }
        
        setStatusBarIcon(context, true);
    }
    
    Calendar c = Calendar.getInstance();
    c.setTimeInMillis(alarm.time);
    String timeString = formatDayAndTime(context, c);
    saveNextAlarm(context, timeString);
} 
else 
{
    if(UtilsAlarm.isLollipopOrLater())
    {
        am.cancel(operation);
    }
    else
    {
        am.cancel(sender);
        setStatusBarIcon(context, false);
    }

    saveNextAlarm(context, "");
}

Intent i = new Intent(NEXT_ALARM_TIME_SET);
context.sendBroadcast(i); }

So if we're on a version lower to Lollipop, it is still working great. However, for Lollipop devices, the icon is displayed when an alarm is enabled but if you disable it (and there are no other alarms enabled), it is currently cancelled from the next coming alarm (expected result) but the icon is still present on the notification bar.

Anyone has an idea of the issue?

Thansk for your help.

Community
  • 1
  • 1
  • This looks correct and sounds like a bug. Have you tested on multiple 5.x devices? The docs say "The system _may_ choose to display information about this alarm to the user" - which indicates to me it might be an implementation detail for the hardware manufacturer. – Adam S May 16 '15 at 12:26
  • Thank you Adam for your comment. I followed it and asked several people with different 5.X devices to try and all encountered the same result : the icon is still showed. – MatrixAndroidLife May 17 '15 at 08:57
  • Have you tried using the same flags for both creating & cancelling? Currently you're creating with a 0 flag and cancelling with `FLAG_NO_CREATE`. – Adam S May 17 '15 at 14:45
  • Yes, in fact I was using the same flag at first and then changed to the method used in the Android stock alarm on Lollipop [here](https://android.googlesource.com/platform/packages/apps/DeskClock/+/android-5.1.1_r1/src/com/android/deskclock/alarms/AlarmNotifications.java) (Line 43) – MatrixAndroidLife May 18 '15 at 05:05

2 Answers2

2

Your problem is in the line int flags = alarm == null ? PendingIntent.FLAG_NO_CREATE : 0;

You are telling the system to assign null to PendingIntent operation, because a corresponding intent already existed from the previous time you were in this method (see doc for FLAG_NO_CREATE).

Later when you call am.cancel(operation); that has no effect at all, since operation == null. Your alarm is still registered in the system. The only reason why nothing happens when the alarm goes off is that you cancelled the intent (not the alarm) in the previous line: PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);. So your assertion is wrong when you say "it is currently cancelled from the next coming alarm (expected result)". The alarm was not cancelled; it was just its intent that was cancelled.

I recommend you to use FLAG_UPDATE_CURRENT.

sorianiv
  • 4,845
  • 1
  • 23
  • 27
  • 1
    Hi ! Thank you for your answer :) ... I've changed each PendingIntent.FLAG_CANCEL_CURRENT by PendingIntent.FLAG_UPDATE_CURRENT and it seems to be working now ! – MatrixAndroidLife Sep 14 '15 at 20:33
1

I have solved it changing my PendingIntent.FLAG_CANCEL_CURRENT to PendingIntent.FLAG_UPDATE_CURRENT in my broadcast call