How to WhiteList app in Doze mode Android 6.0

67,594

Solution 1

Add permission

<uses-permission 
android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>

request whitelist your app

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    Intent intent = new Intent();
    String packageName = getPackageName();
    PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
    if (!pm.isIgnoringBatteryOptimizations(packageName)) {
        intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
        intent.setData(Uri.parse("package:" + packageName));
        startActivity(intent);
    }
}

Solution 2

It is not possible to disable battery optimizations (=whitelist application for doze mode) without user interaction on Android M preview 3.

It can be done with user interaction this way:

Intent intent = new Intent();
String packageName = context.getPackageName();
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
if (pm.isIgnoringBatteryOptimizations(packageName))
    intent.setAction(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
else {
    intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
    intent.setData(Uri.parse("package:" + packageName));
}
context.startActivity(intent);

Solution 3

I think this helper class should cover all your needs.

To use it to request the OS to white-list your app, you can use prepareIntentForWhiteListingOfBatteryOptimization. If you get null, it means you don't need it, or that you can't use it. You can use the other function to query a better state of what you are in.

public class PowerSaverHelper {
    public enum PowerSaveState {
        ON, OFF, ERROR_GETTING_STATE, IRRELEVANT_OLD_ANDROID_API
    }

    public enum WhiteListedInBatteryOptimizations {
        WHITE_LISTED, NOT_WHITE_LISTED, ERROR_GETTING_STATE, UNKNOWN_TOO_OLD_ANDROID_API_FOR_CHECKING, IRRELEVANT_OLD_ANDROID_API
    }

    public enum DozeState {
        NORMAL_INTERACTIVE, DOZE_TURNED_ON_IDLE, NORMAL_NON_INTERACTIVE, ERROR_GETTING_STATE, IRRELEVANT_OLD_ANDROID_API, UNKNOWN_TOO_OLD_ANDROID_API_FOR_CHECKING
    }

    @NonNull
    public static DozeState getDozeState(@NonNull Context context) {
        if (VERSION.SDK_INT < VERSION_CODES.LOLLIPOP)
            return DozeState.IRRELEVANT_OLD_ANDROID_API;
        if (VERSION.SDK_INT < VERSION_CODES.M) {
            return DozeState.UNKNOWN_TOO_OLD_ANDROID_API_FOR_CHECKING;
        }
        final PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        if (pm == null)
            return DozeState.ERROR_GETTING_STATE;
        return pm.isDeviceIdleMode() ? DozeState.DOZE_TURNED_ON_IDLE : pm.isInteractive() ? DozeState.NORMAL_INTERACTIVE : DozeState.NORMAL_NON_INTERACTIVE;
    }

    @NonNull
    public static PowerSaveState getPowerSaveState(@NonNull Context context) {
        if (VERSION.SDK_INT < VERSION_CODES.LOLLIPOP)
            return PowerSaveState.IRRELEVANT_OLD_ANDROID_API;
        final PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        if (pm == null)
            return PowerSaveState.ERROR_GETTING_STATE;
        return pm.isPowerSaveMode() ? PowerSaveState.ON : PowerSaveState.OFF;
    }


    @NonNull
    public static WhiteListedInBatteryOptimizations getIfAppIsWhiteListedFromBatteryOptimizations(@NonNull Context context, @NonNull String packageName) {
        if (VERSION.SDK_INT < VERSION_CODES.LOLLIPOP)
            return WhiteListedInBatteryOptimizations.IRRELEVANT_OLD_ANDROID_API;
        if (VERSION.SDK_INT < VERSION_CODES.M)
            return WhiteListedInBatteryOptimizations.UNKNOWN_TOO_OLD_ANDROID_API_FOR_CHECKING;
        final PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        if (pm == null)
            return WhiteListedInBatteryOptimizations.ERROR_GETTING_STATE;
        return pm.isIgnoringBatteryOptimizations(packageName) ? WhiteListedInBatteryOptimizations.WHITE_LISTED : WhiteListedInBatteryOptimizations.NOT_WHITE_LISTED;
    }

    @TargetApi(VERSION_CODES.M)
    @RequiresPermission(permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)
    @Nullable
    public static Intent prepareIntentForWhiteListingOfBatteryOptimization(@NonNull Context context, @NonNull String packageName, boolean alsoWhenWhiteListed) {
        if (VERSION.SDK_INT < VERSION_CODES.LOLLIPOP)
            return null;
        if (ContextCompat.checkSelfPermission(context, permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) == PackageManager.PERMISSION_DENIED)
            return null;
        final WhiteListedInBatteryOptimizations appIsWhiteListedFromPowerSave = getIfAppIsWhiteListedFromBatteryOptimizations(context, packageName);
        Intent intent = null;
        switch (appIsWhiteListedFromPowerSave) {
            case WHITE_LISTED:
                if (alsoWhenWhiteListed)
                    intent = new Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
                break;
            case NOT_WHITE_LISTED:
                intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS).setData(Uri.parse("package:" + packageName));
                break;
            case ERROR_GETTING_STATE:
            case UNKNOWN_TOO_OLD_ANDROID_API_FOR_CHECKING:
            case IRRELEVANT_OLD_ANDROID_API:
            default:
                break;
        }
        return intent;
    }

    /**
     * registers a receiver to listen to power-save events. returns true iff succeeded to register the broadcastReceiver.
     */
    @TargetApi(VERSION_CODES.M)
    public static boolean registerPowerSaveReceiver(@NonNull Context context, @NonNull BroadcastReceiver receiver) {
        if (VERSION.SDK_INT < VERSION_CODES.M)
            return false;
        IntentFilter filter = new IntentFilter();
        filter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
        context.registerReceiver(receiver, filter);
        return true;
    }


}

Solution 4

Whitelisting can be done programmatically. To add device in whitelisted applications,run following command from application:

adb shell dumpsys deviceidle whitelist +<package_name>

To remove device from whitelisted applications,run following command from application:

adb shell dumpsys deviceidle whitelist -<package_name>

Solution 5

As far as I know , you cannot whitelist yourself from Doze. Ignore battery optimizations does not disable doze. See here: https://code.google.com/p/android-developer-preview/issues/detail?id=2225 UPDATE: In the release build of M , you can request ignore battery optimizations which will at least give you normal access to the internet while in Doze mode.

Share:
67,594
Fransis Q
Author by

Fransis Q

Java and Android Developer

Updated on July 05, 2022

Comments

  • Fransis Q
    Fransis Q about 2 years

    This question is related to the Android 6.0 Preview 3 which will be final released at the end of this month.

    I'm testing some stuff in Android 6.0 in the preview 3 from Google on Nexus 5 'hammerhead'.

    The new feature is the "doze mode" - something like deep sleep mode when the network is disabled and phone sleeps, only the SMS, calls or high priority GCM messages can wake it up. But like WhatsApp - in the doze mode it receives the messages after 2 hours or more depends on the timers. But there is a list of 'not optimised' apps called "white list" where u can manually add app.

    Ok, I'd like to find a way to add my application programmatically without user interaction to the "white list app list" which exists in the device in battery settings.

    Trying to use the reflection to get into it I found:

    Within the android.os.IDeviceIdleController there is a method:

    public abstract void addPowerSaveWhitelistApp (String packageNameOfApp)

    But this is an interface... So we can not make an instance of interface.

    There is not yet documentation about this Interface or about methods, or any inheritance tree.

    Maybe you have some idea where i should look for a possibility of programmatically add there my app?

    There is also a method

    public abstract boolean isPowerSaveWhitelistApp (String packageName)

    Which i think should be possible to access somehow?! to check if the app exist on the White List and maybe at the very end hopefully ASK user to add it to the White List.

    So my question is, have anyone of you tried to make something with better result ?? cuz I'm stuck and i think its a dead end.

    for more info: https://newcircle.com/s/post/1739/2015/06/12/diving-into-android-m-doze

  • Fransis Q
    Fransis Q almost 9 years
    How you define Settings ? My IDE can not find Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS somehow... found it. OK. Now to tests :)
  • M66B
    M66B almost 9 years
    See also here: stackoverflow.com/questions/32316491/… Although people downvote my comment, it is actually correct (tested on Android M preview 3).
  • A.Sanchez.SD
    A.Sanchez.SD almost 9 years
    FYI I have tested this several times. setexactallowwhileidle alarms can only trigger every 15 minutes, regardless if ignore batter optimizations is enabled or disabled.
  • A.Sanchez.SD
    A.Sanchez.SD over 8 years
    UPDATE: In the release build, Ignore optimizations impacts network access while in doze.
  • Kotik_o
    Kotik_o over 8 years
    Where we have to write this code? (Intent intent = new Intent(); ------- context.startActivity(intent)?
  • Opiatefuchs
    Opiatefuchs about 8 years
    none of the two AlarmManager methods are working. Maybe device dependant, on Huawei Ascend Mate 7 these methods fail and doesn´t execute. Also if time is more than 15 minutes....Android Bug?
  • Amit Vaghela
    Amit Vaghela about 8 years
    according to release from developer.android.com, please check if device has android-m than this will work but note will be applied.
  • Opiatefuchs
    Opiatefuchs about 8 years
    Thanks for that "hint" but I am pretty sure that MM is installed :) ...this could also be a behaviour of Huawei. Huawei implemented their own Energy saving manager on their devices. Here is running both, the energy managing system from MM AND Huawei. I think they bite each other. I have set my app to white list, protected it and all the other possible settings to be sure it stays alive. Nothing worked. Also contacted Huawei, but answer is still outstanding....
  • Amit Vaghela
    Amit Vaghela about 8 years
    i am glad that it help you. thank you for appriciation.
  • Opiatefuchs
    Opiatefuchs about 8 years
    I talked to a friend, with a LG Nexus (don´t exactly know the model)...here it works. But the thing is, and this I think is not device dependant, the network connection will be suspended. This is pointed out in the docs. And if so, then much chat apps will have a problem, if they are not using GCM. Very sad.....
  • behelit
    behelit over 7 years
    @Kotik_o normally you would put it in your main activity's onCreate. You will also need to save that you have prompted the user because if they choose No, you will still be asking them everytime
  • RaRa
    RaRa over 7 years
    @FransisQ How you define Settings ? My IDE can not find Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS. <uses-sdk android:minSdkVersion="9" android:targetSdkVersion="23" /> i am using eclipse.
  • dieter
    dieter over 7 years
    if pm.isIgnoringBatteryOptimizations(packageName) is true why to request it again?
  • Sharp Edge
    Sharp Edge over 7 years
    This answer has some issues pm.isIgnoringBatteryOptimizations(packageName) if this returns true then it means that your app is already in the whitelist so no need to startActivity for anything !
  • M66B
    M66B over 7 years
    @SharpEdge the intention is to show the settings whether optimizations are enabled or not.
  • Jenix
    Jenix about 7 years
    "Android 5.1 (API level 22) or lower do not fire when the system is in Doze" Could you explain what this means exactly? I'm very confused because Doze was introduced when Android 6.0 came out..
  • elParaguayo
    elParaguayo about 7 years
    Not sure this actually needs root. As far as I know, my phone is not rooted but the above command worked.
  • android developer
    android developer almost 7 years
    isIgnoringBatteryOptimizations is available only from API 23 . Any workaround for API 21-22 ?
  • M66B
    M66B almost 7 years
    @androiddeveloper doze mode was introduced in Android 6, API 23, so there is no doze mode on earlier Android versions and thus there is no workaround needed.
  • android developer
    android developer almost 7 years
    @M66B Correct. I was confusing it with PowerSave mode, which was on 21-22, and that can already be checked if it's enabled. Thank you and sorry.
  • Sanoop Surendran
    Sanoop Surendran over 6 years
    Can you please explain how this works? Slightly confused here. Will this only whitelist for a specific device only or i can achieve this with whichever devices the app runs on?
  • Sanoop Surendran
    Sanoop Surendran over 6 years
    I have tried the solution, tested it with Xiaomi, even if i was able to remove app from battery saving mode, the FCM didn't worked, I know its not the issue with your solution, you solution worked perfectly detecting the mode, But can you please help? Am kind of like stuck at this moment.
  • android developer
    android developer over 6 years
    @Sanoop Sorry, but I've moved on.
  • Shinoo Goyal
    Shinoo Goyal over 6 years
    If you run this command through your code, it will try work on every phone
  • krishnamurthy
    krishnamurthy over 5 years
    Thanks for the answer. This method is asking the user to allow or deny , i am allowing the permission, but not sure about it is ignoring battery optimization or not because if i go and check in setting manually nothing is changed even if i allow the permission . can anyone clarify it ?
  • Kathir
    Kathir over 5 years
    This might get the job done. However, if you do this, your app will not be accepted by the Play Store for publishing. Android Studio will give you a warning regarding the same. Suggested reading
  • Dr.jacky
    Dr.jacky about 5 years
    @Kathir Please take a look at Acceptable use cases for whitelisting > developer.android.com/training/monitoring-device-state/…
  • Virendra Varma
    Virendra Varma almost 5 years
    we have to run this command every time or only once after installation is enough?
  • Ajay Rawat
    Ajay Rawat almost 5 years
    This life-saving answer to run your foreground-service even when your app is killed
  • Narendra Singh
    Narendra Singh about 4 years
    So, how much time does it take to whitelist? Does it immediately whitelist the app?
  • Deepak V
    Deepak V almost 4 years
    Has anyone done this programmatically? I tried doing this using Process builder in Android 10 + Kotlin. it says permission denied. Any help appreciated. My code is below: val adbShellCommand = "dumpsys deviceidle disable" val pb = ProcessBuilder(adbShellCommand) val p: Process try { p = pb.start() val reader = BufferedReader(InputStreamReader(p.inputStream)) //Set the output to a TextView ... } catch (e: Exception) { ... }
  • Deepak V
    Deepak V almost 4 years
    Apologies, I could not get the code to be formatted
  • famfamfam
    famfamfam over 3 years
    dont do this, just modify fcm params to make it appear
  • famfamfam
    famfamfam over 3 years
    @SanoopSurendran, china room need grant other permission, not only doze
  • Rahul Matte
    Rahul Matte about 2 years
    @Sanchez Does it mean works fine in release build? didn't get the point ...impacts network access while in doze
  • Budimir Grom
    Budimir Grom about 2 years
    This is plain wrong. You request ignoring battery optimization in both cases, using different methods. In any real world situation, you'd request it only if it's not already allowed.
  • M66B
    M66B about 2 years
    @BudimirGrom check again, one intent is to request permissions, the other for the settings to disable the permission again.
  • Budimir Grom
    Budimir Grom about 2 years
    @M66B That's incorrect. Please, consult documentation for both.
  • M66B
    M66B about 2 years
    @BudimirGrom it is correct and working fine in my apps
  • Nathiel Paulino
    Nathiel Paulino about 2 years
    Where should I start this code ? after the user is logged ? context.startActivity(intent) we don't need to pass any activity ?