7

I'm setting in my code an alarm to go off in specific time.
The alarm mechanism works great on SDK < 19, but on 19 the alarms aren't fired.
Here is the code where I set the alarm :

public void SetAlarm(Context context, Long executionTime)
{

    AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    Intent intent = new Intent(context, AlarmReciever.class);
    PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    // Only one alarm can live, so cancel previous.
    am.cancel(pi);
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
        am.set(AlarmManager.RTC_WAKEUP, executionTime, pi);
    } else {
        setAlarmFromKitkat(am, executionTime, pi);
    }
}

Since I'm setting the alarm using a Service I use GetApplicationContext() as the context.

The onReceive() code :

@Override
public void onReceive(Context context, Intent intent) {
    for (SchedulerListener listener : listeners) {
        listener.fetchAndRebuildNotification();
    }
}

Here is the declaration of the BroadcastReceiver :

<receiver 
        android:name="com.SagiL.myAppName.BroadCastReceivers.AlarmReciever" />

The callback runs a method in a service (which is still alive when the alarm supposed to fire, notice it doesn't starts one).

This whole thing is a library which is used in my app, and there I declare the receiver the same way.

Sometimes the alarm do fires once, but mostly it doesn't fire at all.

Has anyone experienced such a thing ?
I can't believe it's common to SDK 19 since a lot of apps are using AlarmManager and they will break too if it is common.

dn_c
  • 614
  • 1
  • 9
  • 26
SagiLow
  • 5,721
  • 9
  • 60
  • 115
  • Are you sure that the `AlarmManager` doesn't fire at all? can you ensure that it doesn't fire also in range of 10 minutes? Please see: http://stackoverflow.com/a/20352528/2075420 – MeNa Dec 22 '13 at 18:42
  • It doesn't fire in any range ... it looks like it get unregistered. And when using `setExact()` there should be no range at all. – SagiLow Dec 22 '13 at 18:50

2 Answers2

10

I had a similar problem with my application. I found out that using 0 ad the id in getBroadcast(...); didn't work very well and caused numerous problems.

Try changing the id from 0 to the alarm's real id.

From:

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

To:

PendingIntent pi = PendingIntent.getBroadcast(context, id, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Assaf Gamliel
  • 11,935
  • 5
  • 41
  • 56
  • 1
    How do I get the real ID ? – SagiLow Dec 23 '13 at 15:02
  • 1
    You can set it yourself to whatever you want, make sure every unique alarm have a unique id. – Assaf Gamliel Dec 23 '13 at 15:03
  • 1
    I'm always replacing one alarm with the other, I never 'hold' 2 alarms together, so it's always the same `PI` and same everything, should I still set different ID to each alarm ? – SagiLow Dec 23 '13 at 15:05
  • That what I thought too. But only changing the ID helped me cancel and replace the alarms. – Assaf Gamliel Dec 23 '13 at 15:13
  • Can you please more be clear ? What do you mean changing the ID? random ID ? What do you mean cancel and replace ? – SagiLow Dec 23 '13 at 15:33
  • When I wanted to cancel an alarm, it was just an example. I don't mean a random ID, I mean that each type of alarm should have it's own id. If you have 2 different types of alarms, one for setting action A and one for action B. Each of them should have it's own ID. – Assaf Gamliel Dec 23 '13 at 17:32
  • 1
    As I mentioned, I use only 1 type of alarm, so using 0 as ID shouldn't be any different than any other number. Meaning this is probably not the solution for the problem. – SagiLow Dec 24 '13 at 17:47
  • 4
    The fact is that using 0 and using any other number does make a difference. It's not documented anywhere but based on my experience, using 0 as request code is almost never a good idea. – Muzikant Jan 16 '14 at 08:51
  • I use other id´s than 0, also it does not work correct on android 4.4.2. Must be a buck..... – Opiatefuchs Mar 30 '15 at 12:03
7

It´s a late answer, but may help. In Android KitKat 4.4.xx a battery manager is integrated (my device: Huawei Ascend Mate 7). There is an option to kill background process and services of an app in the battery manager. Don´t know if the options are named similar to the german options, so just try:

  1. go to settings
  2. select save energy
  3. select detailed power consumption
  4. select Screen off: perform further
  5. enable Your app

It sounds simple, but that exactly was my problem. On Samsung Galaxy S3 with ICS everything worked like a charm. But bought a new device, the huawei, with Android 4.4.2, and suddenly my apps alarms didn´t work. After checking the system, I detected that option, enabled my app and now everything is fine. Not everything is a programming answer :) .

UPDATE

Since this answer was made, a lot happened in Android. For everybody with a similar problem: Since update to Marshmallow, there are two problems: first one is like described above, the second one is the doze mode:

Optimitzing Doze

Some devices, like my Huawei Ascend Mate 7, using both energy saving methods. So it isn´t enough to do what is described above. Also, you have to whitelist the app and use the new alarmManager methods setAllowWhileIdle(), setExactAndAllowWhileIdle() and setAlarmClock() .

Possible Problems

By whitelisting your app, you have to tell this the user. You can do it with a simple information at starting your app, for example a AlertDialog and/or you can use ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS intent to start the whitelisting screen. But be aware of this Action, because like reported from some developers, Google can suspend an app from playstore that is calling this action.

setAlarmClockshould also work, but if you do this, an alarm clock icon is on the top.

Testing

I have made some tests with that new documented doze mode and found out, that it usually works. But without whitelisting, the app falling to standby and ´alarmManager´ does not fire anymore, also not with that new methods. I tested it over night and the app is send to standby within about one hour. At a normal situation at day, where the user is active and often moves his device, it works without whitelisting.

Opiatefuchs
  • 9,800
  • 2
  • 36
  • 49