How do I make my android app appear in Ultra Power Saving Mode
Asked Answered
K

3

25

Some samsung devices have an Ultra Power Saving Mode which turns off wifi, turns the screen grayscale and limits usage to a few basic apps.

It however does allow you to add some apps which can then be used. These apps include Facebook and WhatsApp. How do I make my app appear in this list? What changes do I have to make to the app so that it may appear on this list? Or is this list based on a white list maintained by Samsung?

Knotgrass answered 22/8, 2016 at 15:42 Comment(4)
This might help you forum.xda-developers.com/showthread.php?t=2750393Teeming
the funny thing is that facebook is in Ultra Power Saving Mode list :)Rolandorolandson
If your app does a lot of background work, Samsung's built in battery apps will put it in automatically. So, fe, if your app collects location in a service, or, uses JobSchedulars to set work in the future, your odds will get better you'd be on that list. Though, i'm not really sure why you'd want to be there.Synaeresis
It seems like it's up to the manufacturer which apps get on the list, the messenger Signal has the same 'problem'.Michele
S
14

It may be possible using the permission REQUEST_IGNORE_BATTERY_OPTIMIZATIONS. This permission does not require explicit user permission. So will be granted. Although this will not prevent a user manually stopping the application.

From the docs:

This is a normal permission: an app requesting it will always be granted the permission, without the user needing to approve or see it.

ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS will put the app onto the device's whitelist.

isIgnoringBatteryOptimizations will let you know if the app is whitelisted.

some notes from the docs:

Note: most applications should not use this; there are many facilities provided by the platform for applications to operate correctly in the various power saving modes. This is only for unusual applications that need to deeply control their own execution, at the potential expense of the user's battery life. Note that these applications greatly run the risk of showing to the user as high power consumers on their device.

Input: The Intent's data URI must specify the application package name to be shown, with the "package" scheme. That is "package:com.my.app".

It's not something I'd recommend abusing.

There is a list of Acceptable Use Cases for Whitelisting.

In general, your app should not be on the whitelist unless Doze or App Standby break the core function of the app or there is a technical reason why your app cannot use FCM high-priority messages.

Thanks to adsamcik for this latest link.

Selle answered 10/9, 2017 at 15:18 Comment(5)
Disabling battery optimalizations on the device requires user action. They must either confirm a dialog if you use the ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS or disable it themselves. Also "Google Play policies prohibit apps from requesting direct exemption from Power Management features in Android 6.0+ (Doze and App Standby) unless the core function of the app is adversely affected." developer.android.com/training/monitoring-device-state/…Crockery
I had to implement it myself recently so I know how it works first hand. You are granted the permission but that permission only allows you to send the "ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" intent. This intent will show the user a dialog in which it asks them whether they want to disable battery optimalization or not. I found an example of this dialog (the text on differs from version to version) commonsware.com/blog/images/ignore-batt-opt-dialog.pngCrockery
No just found the image there. It is stated that the permission you need to request the optimalization is granted not that the actual process of whitelisting the app is silent.Crockery
This is how to request the permission: https://mcmap.net/q/81179/-how-do-i-properly-fire-action_request_ignore_battery_optimizations-intent/812973Kansas
This doesn't make my app available in Ultra Power Saving Mode on Samsung Galaxy A5.Kansas
T
2
public class UPSM {

private static SQLiteDatabase db;

synchronized public static void CONFIGURE_UPSM(boolean isEnable, String APP_PACKAGE, String APP_LAUNCHER_ACTIVITY) {
    try {
        final String FILE_PATH = "/data/data/com.sec.android.provider.emergencymode/databases/emergency.db";
        final String FILE_PATH_JOURNAL = "/data/data/com.sec.android.provider.emergencymode/databases/emergency.db-journal";
        String command = "adb shell \"su -c cat " + FILE_PATH + "\" > emergency.db";
        Shell.SU.run("chmod 777 " + FILE_PATH);
        Shell.SU.run(command);
        String command_journal = "adb shell \"su -c cat " + FILE_PATH_JOURNAL + "\" > emergency.db-journal";
        Shell.SU.run("chmod 777 " + FILE_PATH_JOURNAL);
        Shell.SU.run(command_journal);
        String COMMAND_ENABLE = "settings put global low_power 1\n" +
                "am broadcast -a android.os.action.POWER_SAVE_MODE_CHANGED --ez mode true\n";
        String COMMAND_DISABLE = "settings put global low_power 0\n" +
                "am broadcast -a android.os.action.POWER_SAVE_MODE_CHANGED --ez mode false\n";
        if (isEnable) {
            Shell.SU.run(COMMAND_ENABLE);
        } else {
            Shell.SU.run(COMMAND_DISABLE);
        }
        File file = new File(FILE_PATH);
        if (file.exists()) {
            if (db == null) {
                db = SQLiteDatabase.openOrCreateDatabase(FILE_PATH, null);
                db = SQLiteDatabase.openDatabase(FILE_PATH, null, SQLiteDatabase.OPEN_READWRITE);
                db.setLockingEnabled(false);
            } else if (!db.isOpen()) {
                db = SQLiteDatabase.openOrCreateDatabase(FILE_PATH, null);
                db = SQLiteDatabase.openDatabase(FILE_PATH, null, SQLiteDatabase.OPEN_READWRITE);
                db.setLockingEnabled(false);
            }
            if (db != null && db.isOpen()) {
                configureLauncherAdd(isEnable, APP_PACKAGE, APP_LAUNCHER_ACTIVITY, db);
                configureLauncherDefault(isEnable, APP_PACKAGE, APP_LAUNCHER_ACTIVITY, db);
                configureWhiteList(isEnable, APP_PACKAGE, db);
                db.close();
                db = null;
            }
        }
    } catch (NullPointerException e) {
        StackTraceLog.write(e, "CONFIGURE_UPSM_1");
    } catch (RuntimeException e) {
        StackTraceLog.write(e, "CONFIGURE_UPSM_1");
    } catch (OutOfMemoryError e) {
        StackTraceLog.write(e, "CONFIGURE_UPSM_1");
    } catch (Exception e) {
        StackTraceLog.write(e, "CONFIGURE_UPSM_1");
    }
}

private static void configureLauncherAdd(boolean isEnable, String APP_PACKAGE, String APP_LAUNCHER_ACTIVITY, SQLiteDatabase db) {
    try {
        boolean isExist = false;
        Cursor cursor = db.rawQuery("select * from launcheradd where package like '" + APP_PACKAGE + "' and class like '" + APP_LAUNCHER_ACTIVITY + "'", null);
        if (cursor != null) {
            if (!cursor.isAfterLast()) {
                cursor.moveToFirst();
                long count = cursor.getCount();
                if (count > 0) {
                    isExist = true;
                }
            }
            cursor.close();
        }
        if (!isExist) {
            ContentValues contentValues = new ContentValues();
            contentValues.put("package", APP_PACKAGE);
            contentValues.put("class", APP_LAUNCHER_ACTIVITY);
            contentValues.put("permission", "1111");
            if (isEnable) {
                contentValues.put("mode", 1);
            } else {
                contentValues.put("mode", 0);
            }
            db.insert("launcheradd", null, contentValues);
        } else {
            ContentValues contentValues = new ContentValues();
            if (isEnable) {
                contentValues.put("mode", 1);
            } else {
                contentValues.put("mode", 0);
            }
            String where = "package like '" + APP_PACKAGE + "' and class like '" + APP_LAUNCHER_ACTIVITY + "'";
            db.update("launcheradd", contentValues, where, null);
        }
    } catch (NullPointerException e) {
        StackTraceLog.write(e, "CONFIGURE_UPSM_2");
    } catch (RuntimeException e) {
        StackTraceLog.write(e, "CONFIGURE_UPSM_2");
    } catch (OutOfMemoryError e) {
        StackTraceLog.write(e, "CONFIGURE_UPSM_2");
    } catch (Exception e) {
        StackTraceLog.write(e, "CONFIGURE_UPSM_2");
    }
}

private static void configureLauncherDefault(boolean isEnable, String APP_PACKAGE, String APP_LAUNCHER_ACTIVITY, SQLiteDatabase db) {
    try {
        boolean isExist = false;
        Cursor cursor = db.rawQuery("select * from launcherdefault where package like '" + APP_PACKAGE + "' and class like '" + APP_LAUNCHER_ACTIVITY + "'", null);
        if (cursor != null) {
            if (!cursor.isAfterLast()) {
                cursor.moveToFirst();
                long count = cursor.getCount();
                if (count > 0) {
                    isExist = true;
                }
            }
            cursor.close();
        }
        if (!isExist) {
            ContentValues contentValues = new ContentValues();
            contentValues.put("package", APP_PACKAGE);
            contentValues.put("class", APP_LAUNCHER_ACTIVITY);
            contentValues.put("position", 1);
            contentValues.put("fixed", 1);
            if (isEnable) {
                contentValues.put("mode", 1);
            } else {
                contentValues.put("mode", 0);
            }
            db.insert("launcherdefault", null, contentValues);
        } else {
            ContentValues contentValues = new ContentValues();
            if (isEnable) {
                contentValues.put("mode", 1);
            } else {
                contentValues.put("mode", 0);
            }
            String where = "package like '" + APP_PACKAGE + "' and class like '" + APP_LAUNCHER_ACTIVITY + "'";
            db.update("launcherdefault", contentValues, where, null);
        }
    } catch (NullPointerException e) {
        StackTraceLog.write(e, "CONFIGURE_UPSM_3");
    } catch (RuntimeException e) {
        StackTraceLog.write(e, "CONFIGURE_UPSM_3");
    } catch (OutOfMemoryError e) {
        StackTraceLog.write(e, "CONFIGURE_UPSM_3");
    } catch (Exception e) {
        StackTraceLog.write(e, "CONFIGURE_UPSM_3");
    }
}

private static void configureWhiteList(boolean isEnable, String APP_PACKAGE, SQLiteDatabase db) {
    try {
        boolean isExist = false;
        Cursor cursor = db.rawQuery("select * from whitelist where pkg like '" + APP_PACKAGE + "'", null);
        if (cursor != null) {
            if (!cursor.isAfterLast()) {
                cursor.moveToFirst();
                long count = cursor.getCount();
                if (count > 0) {
                    isExist = true;
                }
            }
            cursor.close();
        }
        if (!isExist) {
            ContentValues contentValues = new ContentValues();
            contentValues.put("pkg", APP_PACKAGE);
            if (isEnable) {
                contentValues.put("allowflag", 1);
            } else {
                contentValues.put("allowflag", 0);
            }
            db.insert("whitelist", null, contentValues);
        } else {
            ContentValues contentValues = new ContentValues();
            if (isEnable) {
                contentValues.put("allowflag", 1);
            } else {
                contentValues.put("allowflag", 0);
            }
            String where = "pkg like '" + APP_PACKAGE + "'";
            db.update("whitelist", contentValues, where, null);
        }
    } catch (NullPointerException e) {
        StackTraceLog.write(e, "CONFIGURE_UPSM_4");
    } catch (RuntimeException e) {
        StackTraceLog.write(e, "CONFIGURE_UPSM_4");
    } catch (OutOfMemoryError e) {
        StackTraceLog.write(e, "CONFIGURE_UPSM_4");
    } catch (Exception e) {
        StackTraceLog.write(e, "CONFIGURE_UPSM_4");
    }
}

}

//IGNORE StackTraceLog 
Triplex answered 12/4, 2019 at 5:44 Comment(2)
Please elaborate the answer by providing explanation on how the code tries to solve the issue mentioned in the question.Lawannalawbreaker
The Shell class is not available? Does this need a rooted phone?Kansas
H
0

A solution not based in code but in a 3rd party app and the end user is installing UPSM+ app.

From this app you can make any installed app available for UPSM. Also from this app you can control the behaviour with options as 'always enabled', 'don't kill if turn off screen',...

Holding answered 22/2, 2021 at 9:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.