Alarm Manager does not work in background on Android 6.0
E

3

13

This is my Activity code,

Long time = new GregorianCalendar().getTimeInMillis()+20000;//Setting alarm after 20 sec
Intent intentAlarm = new Intent("alarm");
intentAlarm.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intentAlarm.putExtra("req_code",10);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,10, intentAlarm, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, time, pendingIntent);

These are all the permissions that I have in my app,

  <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.GET_ACCOUNTS"/>
    <uses-permission android:name="com.myapp.pack.permission.SET_ALARM"/>
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

This is my BroadcastReceiver code,

@Override
public void onReceive(Context context, Intent intent) {
        SharedPreferences sharedPreferences =
        context.getSharedPreferences( "mydata", Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putBoolean("elligible",true);
        editor.apply();

    }

I have registered my BroadcastReceiver in the manifest,

 <receiver android:name="com.myapp.pack.AlarmReciever" android:enabled="true">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
            <action android:name="alarm" />
        </intent-filter>
    </receiver>

The above code successfully executes the BroadcastReceiver on pre-MarshMallow devices in the background ,but on a MarshMallow device ,the BroadcastReceiver does not get executed. Does anyone know what could be happening here? Thanks.

Expiate answered 20/12, 2015 at 7:5 Comment(0)
R
26

There are a couple of things you can try which, when used in concert, should be able to cut through all of the idle/standby/doze modes (irrespective of OS version).

1. Use a WakefulBroadcastReceiver instead of an ordinary BroadcastReceiver. Make sure you include the WAKE_LOCK permission to use it correctly.

2. Use the setExactAndAllowWhileIdle() method (on API 23 & above) to schedule the Intent for the receiver:

if(Build.VERSION.SDK_INT < 23){
    if(Build.VERSION.SDK_INT >= 19){
        setExact(...);
    }
    else{
        set(...);
    }
}
else{
    setExactAndAllowWhileIdle(...);
}

References:

1. Alarm manager for background services.

2. A flowchart for background work, alarms, and your Android app.

Rastus answered 20/12, 2015 at 10:24 Comment(9)
So if I use setExactAndAllowWhileIdle() will I have to change minimum sdk version of my app to 23?Expiate
setExact() is available only from API 19. So you need to do that check as well inelse if in the condition in the snippet.Bethelbethena
setExactAndAllowWhileIdle() is not consistently giving desire output...in several devices like gionee, xiaomi, samsung and others more.....in some devices its not fire on perfect time, in others its not fire......Luxembourg
@himCream: Could you kindly describe your problem in more detail, preferably in a new question?Rastus
My problem is: I have following code : alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), sender); setting alarm every 30 min with WakefulBroadcastReceiver but in some devices some times its missing to calling the alarm and some time its calling alarm after 2-3 min by desire time.....i m confirming it by logsLuxembourg
What device are you using? I suggest you check it in the emulator first and confirm that it is working properly ...Rastus
Isn't doze mode supposed to ignore wake locks? Can anybody confirm if this works as intended?... Also will it allow network ops?Surplice
@Kushan: the setExactAndAllowWhileIdle() and setAlarmClock() methods surely cut through Doze. The WakefulBroadcastReceiver is an additional scaffold.Rastus
I read somewhere that even if the alarms fire... The service/ receiver won't start... This method sets your app in whitelist for ten seconds... I'm worried whether this will let my receiver or an intent service work and do network operation...Surplice
W
7

The reason can be Doze mode introduced in Android 6.0 Marshmallow. Use setAlarmclock() instead of set(). It's designed specifically for alarm clocks and may be able to cut through doze. There are a few adb commands you can use to manually put a phone into doze or app standby mode:

https://developer.android.com/preview/features/power-mgmt.html

If that isn't able to wake your app up, there's the surefire method setExactAndAllowWhileIdle() is designed to wake the phone from doze no matter what. Worst case scenario, you can wake your app up with this method and use the wakeup to schedule the next alarm.

Reference: How to make Alarm Manager work when Android 6.0 in Doze mode?

Witherspoon answered 20/12, 2015 at 7:13 Comment(1)
Ok i'll give it a try.Expiate
R
0

In my experiment, AlarmManagerCompat + setAlarmClock is stable to wake up in doze mode. I use xiaomi device which use MIUI.

AlarmManagerCompat.setAlarmClock(alarmManager, time, showIntent, pendingIntent)

Please vote up if this benefit for you, cheers!

Respire answered 27/2, 2020 at 15:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.