问题
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?
回答1:
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.
回答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
来源:https://stackoverflow.com/questions/39083670/how-do-i-make-my-android-app-appear-in-ultra-power-saving-mode