59

Android 6 and 7 have some power optimizations (doze mode) which restrict app networking when device is not used.

User may disable optimization mode for any app in Battery settings:

android settings screenshot

Is it possible to check if optimization is enabled for my app or not? I need to ask user to disable optimization for better app functionality, but I don't know how to check it programatically.

Jean-François Côté
  • 4,200
  • 11
  • 52
  • 88
Nik
  • 7,114
  • 8
  • 51
  • 75
  • 3
    Note that it's not allowed to ask user to whitelist your app unless it satisfies the requirements here: https://developer.android.com/training/monitoring-device-state/doze-standby#whitelisting-cases – Prasad Pawar Aug 02 '19 at 11:00

4 Answers4

66

Add this permission in your manifest.

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

Request White-list / optimization enabled 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);
        }
    }
  • 27
    Yes it works perfectly :D But only thing is that the app will be rejected from playstore and you'll lose all your business! – Rohit TP Apr 14 '20 at 06:25
  • 4
    @RohitTP Can you please elaborate why adding this check in the app makes it a candidate for a rejection from PlayStore? – sud007 Apr 26 '20 at 18:09
  • Well I guess, as I have checked. Adding permission in the manifest is not required if you just want to check battery optimization and display a message to the user. – sud007 Apr 26 '20 at 18:37
  • 14
    @sud007 'ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS' is a dangerous permission. Google doesn't like having apps having this anywhere inside their code(https://developer.android.com/training/monitoring-device-state/doze-standby). This permission & action is a bit dangerous since if we add this we allow the app to directly show an android pop up asking user to turn off battery optimizations for this app. Instead, what you should do is have 'ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS' which takes user to list of apps where he has to search for your app & disable battery optimisations manually. – Rohit TP Apr 29 '20 at 10:42
  • 1
    @RohitTP Yes buddy I checked all the details about the same and got educated about the gravity, and hence added my second comment. Thanks anyways! :) – sud007 Apr 30 '20 at 09:03
  • For xiaumi 8 this doesn't work (I got activity is not found, even I put in manifest, and do some safeguard check). – Eitan Aug 16 '20 at 08:21
  • 1
    some apps like true caller gets this permission by default, without asking the user to enable it, how is this possible? – Samer Alkhatib Jun 30 '21 at 13:46
  • 3
    probably money and nepotism – Vivek Jul 10 '21 at 19:48
  • 1
    @SamerAlkhatib setting the app as an "Default App" -> True Caller is a Phone App. WILL turn off battery optimisations. I noticed that with our app. from the moment you set it as default, it sets it to "Not Optimised" – rosu alin Nov 17 '21 at 09:44
  • after granting battery OPTIMIZATIONS permission this is not woking – karan Dec 04 '21 at 06:24
  • @RohitTP According to google docs, It's not a problem if the core function of the app is adversely affected – faridfedora May 13 '22 at 19:15
41

How to write this in Kotlin

  1. Check if optimization is enabled
    /**
     * return true if in App's Battery settings "Not optimized" and false if "Optimizing battery use"
     */
    fun isIgnoringBatteryOptimizations(context: Context): Boolean {
        val pwrm = context.applicationContext.getSystemService(Context.POWER_SERVICE) as PowerManager
        val name = context.applicationContext.packageName
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            return pwrm.isIgnoringBatteryOptimizations(name)
        }
        return true
    }
  1. Check if Optimization enabled, open optimizations Activity
    fun checkBattery() {
        if (!isIgnoringBatteryOptimizations() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            val name = resources.getString(R.string.app_name)
            Toast.makeText(applicationContext, "Battery optimization -> All apps -> $name -> Don't optimize", Toast.LENGTH_LONG).show()

            val intent = Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS)
            startActivity(intent)
        }
    }
Lioness100
  • 8,260
  • 6
  • 18
  • 49
Evgenii Vorobei
  • 1,457
  • 18
  • 20
  • 5
    Why ">= VERSION_CODES.LOLLIPOP_MR1" ? ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS was added in Android M. – adriennoir Sep 22 '18 at 16:07
  • 2
    Thanks for sharing the complete solution. Works like a charm! – sud007 Apr 26 '20 at 18:48
  • you're going to need [REQUEST_IGNORE_BATTERY_OPTIMIZATIONS](https://developer.android.com/reference/android/Manifest.permission#REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) permission for that second part to work – lasec0203 Sep 23 '20 at 02:59
  • Yup like lasec0203 has pointed out, please add to your manifest. – Bharadwaj Giridhar Sep 18 '21 at 04:48
  • 2
    According to CommonsWare, If you want to use ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, to lead the user straight to a page specific for your app and the whitelist, you need to request REQUEST_IGNORE_BATTERY_OPTIMIZATIONS in the manifest, but you do not need to use runtime permissions code for it. If you want to avoid the permission, use ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS instead. So if you are using above answer you will not need REQUEST_IGNORE_BATTERY_OPTIMIZATIONS permission. – Chaitanya Karmarkar Oct 07 '21 at 04:03
40

This one was a bit tricky to track down: here's what you are looking for

PowerManager.isIgnoringBatteryOptimizations()

OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
FriendlyMikhail
  • 2,857
  • 23
  • 39
  • 4
    in case you want to be able to get user to flip it: https://developer.android.com/reference/android/provider/Settings.html#ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS – FriendlyMikhail Aug 31 '16 at 18:32
  • 1
    Does this apply for manufacturer modified ROMs too or only for Nexus/Pixel/A1 builds? – bearlysophisticated Jan 08 '18 at 12:55
  • @EfiMK I couldn't do a comprehensive testing but I can confirm that `PowerManager.isIgnoringBatteryOptimizations()` method is working on Samsung and Huawei devices. I would say it's available for any manufacturer ROM. – bearlysophisticated May 15 '18 at 08:15
16

Sample Code :

 PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (pm != null && !pm.isIgnoringBatteryOptimizations(getPackageName())) {
                    askIgnoreOptimization();
                } else {
                   // already ignoring battery optimization code here next you want to do
                }
            } else {
           // already ignoring battery optimization code here next you want to do
            }

Declare static variable

private static final int IGNORE_BATTERY_OPTIMIZATION_REQUEST = 1002;

show dialog for BATTERY_OPTIMIZATIONS

 private void askIgnoreOptimization() {

        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
            Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
            intent.setData(Uri.parse("package:" + getPackageName()));
            startActivityForResult(intent, IGNORE_BATTERY_OPTIMIZATION_REQUEST);
        } else {
            openNextActivity();
        }
    }

also need to add permission to manifest file i.e as below

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

Maybe this code is helpful to you!

PJain
  • 526
  • 2
  • 14
Yogesh Rathi
  • 6,331
  • 4
  • 51
  • 81
  • @yogesh how to get to know if he has tapped Allow/Deny and where? – Ramesh Nov 15 '21 at 11:54
  • @Ramesh you can verify on onActivityResult – Yogesh Rathi Nov 16 '21 at 09:42
  • @YogeshRathi I am developing app using React Native. So, I need to return boolean in the askIgnoreOptimization() method itself where I am startingActivity. – Ramesh Nov 16 '21 at 12:44
  • @Ramesh I am not sure of React Native, If you find an answer, please free to update the question – Yogesh Rathi Jan 13 '22 at 07:07
  • @Ramesh did you find a solution? This is exactly where I'm stuck as well – Keselme May 25 '22 at 12:11
  • @Keselme I fixed this issue by using AppState. Using AppState, I was able to detect if App is in foreground or background. When the state changes from Background to Foreground, I check if permission is given or not in the screen. For some devices like Xiomi, we may need to add some delay and check the permission state as it may return always false. – Ramesh May 26 '22 at 08:01
  • @Ramesh, If you're still intreated, I think I have a solution that doesn't require the AppState thing. Make your module implement `ActivityEventListener`. Then add it as a listener on your module's context. Then call for `startActivityForRestult` and implement `onActivityResult`. Here you can check if the permission is granted and resolve it via promise. I'm pretty sure it works, though I'm still testing different scenarios with this approach – Keselme Jun 15 '22 at 21:44