Alarm Manager issue in Android 6.0 Doze mode
S

2

11

I've made an app that always worked until Android 6.0. I think it's the Doze feature that it's not allowing my Alarm to fire.

I use sharedpreferences to handle the options:

//ENABLE NIGHT MODE TIMER
    int sHour = blockerTimerPreferences.getInt("sHour", 00);
    int sMinute = blockerTimerPreferences.getInt("sMinute", 00);

    Calendar sTime = Calendar.getInstance();
    sTime.set(Calendar.HOUR_OF_DAY, sHour);
    sTime.set(Calendar.MINUTE, sMinute);

    Intent enableTimer = new Intent(context, CallReceiver.class);
    enableTimer.putExtra("activate", true);
    PendingIntent startingTimer = PendingIntent.getBroadcast(context, 11002233, enableTimer, PendingIntent.FLAG_UPDATE_CURRENT);
    AlarmManager sAlarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    sAlarm.setRepeating(AlarmManager.RTC_WAKEUP,
            sTime.getTimeInMillis(),
            AlarmManager.INTERVAL_DAY, startingTimer);

Any clue of whats wrong here?

This is an app to block calls. Thank you!

EDIT: I have 3 files (more but...) like:

MainActivity (All code)
CallReceiver (Broadcast that triggers the alarm again (reboot etc))
CallReceiverService (Handles the call / phone state)
Swerve answered 25/2, 2016 at 13:54 Comment(5)
Use adb shell dumpsys alarm to confirm that your alarm is scheduled. Note that setRepeating() is inexact on Android 4.4+. "This is causing battery drain too" -- that seems unlikely. Code that does not run should consume no battery.Stratovision
Hi @CommonsWare, 52 wakes and 52 alarms... It's always firering the alarms. setRepeating() will fire in that minute, no issue I think.Swerve
@Swerve Did you make it work? Can we implement alarmManager.setRepeating() in the doze mode?Haffner
@Haffner only like this and creating a service to check on boot etc. setExactAndAllowWhileIdle on >M and on old versions setExactSwerve
setExact wont repeat. What if I need to make it repeat? @SwerveHaffner
L
14

The Doze mode will delay your alarm until the next maintenance window. To avoid the Doze mode to block your alarm, you can use setAndAllowWhileIdle(), setExactAndAllowWhileIdle() or setAlarmClock(). You will have about 10s to execute your code, and set your next alarm (not more than once per 15min for methods with _AndAllowWhileIdle though)

If you want to test the Doze mode, you can use ADB command:

  1. Configure a hardware device or virtual device with an Android 6.0 (API level 23) or higher system image.

  2. Connect the device to your development machine and install your app.

  3. Run your app and leave it active.
  4. Shut off the device screen. (The app remains active.) Force the system to cycle through Doze modes by running the following commands:

    adb shell dumpsys battery unplug

    adb shell dumpsys deviceidle step

  5. You may need to run the second command more than once. Repeat it until the device state changes to idle.

  6. Observe the behavior of your app after you reactivate the device. Make sure the app recovers gracefully when the device exits Doze.

Edit: Add setAlarmClock example

Don't forget to check the SDK level (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)

AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent intent = new Intent(this, MyAlarmReceiver.class); //or just new Intent() for implicit intent 
//set action to know this come from the alarm clock
intent.setAction("from.alarm.clock");
PendingIntent pi = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
//Alarm fire in 5s.
am.setAlarmClock(new AlarmManager.AlarmClockInfo(System.currentTimeMillis() + 5000, pi), pi);
Lexicology answered 26/2, 2016 at 16:59 Comment(8)
Hi @Lexicology , just replace setRepeating for the setAlarmClock? With the same params? Can you please make an example? Thank you!Swerve
I edit my answer, but this is not very different of the others set alarm methods.Lexicology
This is just an example to fire an alarm after 5s. Choose the time you want.Lexicology
Hi @xiaomi, that intent.setAction("from.alarm.clock"); it's showing the alarm icon on my phone, if I delete, any issue?Swerve
Ah I didn't see that setAlarmClock will bring the clock icon into the status bar. Btw the set action is only for you when you check your receiver intent.getAction(). To remove the icon you will have to use another method than setAlarmClock()Lexicology
Hi @xiaomi, can you please tell me one? Since this is very annoying. It works but I think no one will like that icon there..Swerve
Just use setAndAllowWhileIdle insteadLexicology
@Lexicology What if we need to implement alarmManager.setRepeating() in the doze mode? How can we implement that? Can we use setAlarmClock like u mentioned above?Haffner
F
2

If the device is in doze mode, you need to use one of these API: setExactAndAllowWhileIdle or setAndAllowWhileIdle.

Note that there is no API for waking the device up while in doze mode for a repeating alarm, so if you need a repeating alarm to wake the device while in doze, you have to use the APIs above and re-arm the timer at every occurrence of the timer firing.

Fagot answered 26/2, 2016 at 16:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.