AlarmManager not working when device is sleeping in Android
I need some of the code to run every time, even if the application is killed or the device sleeps.
I am using AlarmManager
to achieve this and it works, but when the device sleeps for about five minutes, it Service
no longer gets called ... Does anyone know what I am doing wrong?
here is my code:
public class Profiler extends IntentService {
public static final int ALARM_MANAGER_ID = 21436587;
public Profiler() {
super("Profiler");
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
JodaTimeAndroid.init(getApplicationContext());
System.out.println("Testing profiles");
List<Profile> profiles = MainActivity.getStoredProfiles(getApplicationContext());
if (profiles != null) {
for (Profile profile : profiles) {
if(profile.check()) {
profile.set(getApplicationContext());
}
}
}
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent intent2 = new Intent(getApplicationContext(), Profiler.class);
PendingIntent pIntent = PendingIntent.getService(getApplicationContext(), ALARM_MANAGER_ID, intent2, PendingIntent.FLAG_CANCEL_CURRENT);
alarmManager.setExact(AlarmManager.RTC_WAKEUP, DateTime.now().plusSeconds(10).getMillis(), pIntent);
}
}
And one more question. Is this method a reliable service call?
Here is the log
07-24 11:31:24.654 17689-19078/cz.fjerabek.soundprofiler I/System.out: {"type":"Time","hour":0,"minute":0}
07-24 11:31:34.671 17689-20364/cz.fjerabek.soundprofiler I/System.out: Testing profiles
07-24 11:31:34.673 17689-20364/cz.fjerabek.soundprofiler I/System.out: {"type":"Time","hour":11,"minute":15}
07-24 11:31:34.674 17689-20364/cz.fjerabek.soundprofiler I/System.out: {"type":"Time","hour":0,"minute":0}
07-24 11:31:44.692 17689-21571/cz.fjerabek.soundprofiler I/System.out: Testing profiles
07-24 11:31:44.693 17689-21571/cz.fjerabek.soundprofiler I/System.out: {"type":"Time","hour":11,"minute":15}
07-24 11:31:44.694 17689-21571/cz.fjerabek.soundprofiler I/System.out: {"type":"Time","hour":0,"minute":0}
07-24 11:31:54.704 17689-22753/cz.fjerabek.soundprofiler I/System.out: Testing profiles
07-24 11:31:54.705 17689-22753/cz.fjerabek.soundprofiler I/System.out: {"type":"Time","hour":11,"minute":15}
07-24 11:31:54.706 17689-22753/cz.fjerabek.soundprofiler I/System.out: {"type":"Time","hour":0,"minute":0}
07-24 11:32:04.717 17689-24015/cz.fjerabek.soundprofiler I/System.out: Testing profiles
07-24 11:32:04.718 17689-24015/cz.fjerabek.soundprofiler I/System.out: {"type":"Time","hour":11,"minute":15}
07-24 11:32:04.718 17689-24015/cz.fjerabek.soundprofiler I/System.out: {"type":"Time","hour":0,"minute":0}
07-24 11:35:29.032 17689-17475/cz.fjerabek.soundprofiler I/System.out: Testing profiles
07-24 11:35:29.040 17689-17475/cz.fjerabek.soundprofiler I/System.out: {"type":"Time","hour":11,"minute":15}
07-24 11:35:29.050 17689-17475/cz.fjerabek.soundprofiler I/System.out: {"type":"Time","hour":0,"minute":0}
[ 07-24 11:35:29.056 17476:17476 I/ ]
power log dlsym ok
the application was launched at 11:31 am and now its 11:40, as you can see, the last execution of the code was at 11:35 and before that at 11:32 its 3 minutes, then it seems like it is called every 5 minutes.
I start the service with:
Intent bgServiceIntent = new Intent(getApplicationContext(), Profiler.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
if(checkNotificationPolicy(getApplicationContext())) {
startService(bgServiceIntent);
}
} else {
startService(bgServiceIntent);
}
The device I'm using: HUAWEI P9 lite (VNS-L21)
source to share
Doze is most likely the cause of the problem .
From their docs regarding AlarmManager
:
To aid in scheduling alarms, Android 6.0 (API Level 23) introduces two new methods
AlarmManager
:setAndAllowWhileIdle()
andsetExactAndAllowWhileIdle()
. With these methods you can set alarms to be triggered even if the device is in Doze mode.
You should call the appropriate method AlarmManager
based on the API level to make sure the alarm goes off even when the device is sleeping:
if (Build.VERSION.SDK_INT >= 23) {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,
alarmMillis, alarmIntent);
} else if (Build.VERSION.SDK_INT >= 19) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP,
alarmMillis, alarmIntent);
} else {
alarmManager.set(AlarmManager.RTC_WAKEUP,
alarmMillis, alarmIntent);
}
Consider the following:
Neither
setAndAllowWhileIdle()
norsetExactAndAllowWhileIdle()
can a fire alarm be more than once every 9 minutes, per app.
As you said, you are testing a Huawei device.
Huawei (among other manufacturers) has implemented some battery saving features that can prevent alarms from triggering. You must add your application to "secure" applications.
Pay attention to the following questions: 1 and 2
It is not recommended to do this programmatically, the right solution might be to warn your users at startup (for example with help AlertDialog
) to manually make your application "protected" in Battery Manager.
source to share