Java 如何在 Android 6.0 打盹模式下将应用列入白名单
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32627342/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to WhiteList app in Doze mode Android 6.0
提问by Fransis Q
This question is related to the Android 6.0 Preview 3 which will be final released at the end of this month.
此问题与将于本月底最终发布的 Android 6.0 Preview 3 有关。
I'm testing some stuff in Android 6.0 in the preview 3 from Google on Nexus 5 'hammerhead'.
我正在 Nexus 5“hammerhead”上的 Google 预览版 3 中测试 Android 6.0 中的一些内容。
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.
新功能是“打盹模式”——类似于网络禁用且手机休眠时的深度睡眠模式,只有短信、电话或高优先级 GCM 消息才能将其唤醒。但就像 WhatsApp - 在打盹模式下,它会在 2 小时或更长时间后收到消息,具体取决于计时器。但是有一个名为“白名单”的“未优化”应用程序列表,您可以在其中手动添加应用程序。
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:
在 android.os.IDeviceIdleController 中有一个方法:
public abstract void addPowerSaveWhitelistApp (String packageNameOfApp)
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)
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
更多信息:https: //newcircle.com/s/post/1739/2015/06/12/diving-into-android-m-doze
回答by M66B
It is not possible to disable battery optimizations (=whitelist application for doze mode) without user interaction on Android M preview 3.
在 Android M 预览版 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);
回答by A.Sanchez.SD
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=2225UPDATE: 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.
据我所知,您不能将自己从 Doze 中列入白名单。忽略电池优化不会禁用打瞌睡。请参阅此处:https: //code.google.com/p/android-developer-preview/issues/detail?id =2225 更新:在 M 的发布版本中,您可以请求忽略电池优化,这至少会给您正常在打盹模式下访问互联网。
回答by Amit Vaghela
UPDATE
更新
When the device is stationary again, with screen off and on battery for a period of time, Doze applies the full CPU and network restrictions on PowerManager.WakeLock, AlarmManager alarms, and GPS/Wi-Fi scans.
当设备再次静止时,屏幕关闭并使用电池一段时间,Doze 会对PowerManager.WakeLock、AlarmManager 警报和 GPS/Wi-Fi 扫描应用完整的 CPU 和网络限制。
Visit Use Cases for Whitelistingfor more detail.
The table below highlights the acceptable use cases for requesting or being on the Battery Optimizations exceptions whitelist. 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 GCM high-priority messages.
下表突出显示了请求或列入电池优化例外白名单的可接受用例。一般来说,除非 Doze 或 App Standby 破坏了应用程序的核心功能,或者您的应用程序由于技术原因无法使用 GCM 高优先级消息,否则您的应用程序不应在白名单中。
Doze is particularly likely to affect activities that AlarmManager alarmsand timers manage, because alarms in Android 5.1 (API level 22) or lower do not fire when the system is in Doze.
打瞌睡特别有可能影响 AlarmManager警报和计时器管理的活动,因为当系统处于打盹状态时,Android 5.1(API 级别 22)或更低版本中的警报不会触发。
Android 6.0 (API level 23) introduces two new AlarmManager methods: setAndAllowWhileIdle()
and setExactAndAllowWhileIdle()
. With these methods, you can set alarms that will fire even if the device is in Doze.
Android 6.0(API 级别 23)引入了两个新的 AlarmManager 方法:setAndAllowWhileIdle()
和setExactAndAllowWhileIdle()
. 使用这些方法,您可以设置即使设备处于打盹状态也会触发的警报。
Note: Neither setAndAllowWhileIdle()
nor setExactAndAllowWhileIdle()
can fire alarms more than once per 15 minutes per app.
注意:每个应用程序每 15 分钟发出一次警报,setAndAllowWhileIdle()
也setExactAndAllowWhileIdle()
不能超过一次。
回答by jefry Hymany
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);
}
}
回答by Shinoo Goyal
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>
回答by android developer
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.
要使用它来请求操作系统将您的应用程序列入白名单,您可以使用 prepareIntentForWhiteListingOfBatteryOptimization。如果您得到 null,则表示您不需要它,或者您不能使用它。您可以使用另一个函数来查询您所处的更好状态。
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;
}
}