Java 如何在打瞌睡模式下将应用程序列入白名单Android 6.0

Java 如何在打瞌睡模式下将应用程序列入白名单Android 6.0,java,android,preview,android-6.0-marshmallow,Java,Android,Preview,Android 6.0 Marshmallow,这个问题与Android 6.0预览版3有关,它将于本月底最终发布 我正在Nexus5“锤头”上的谷歌预览版3中测试Android 6.0中的一些东西 新功能是“打瞌睡模式”——类似于深度睡眠模式,当网络被禁用且手机处于睡眠状态时,只有短信、呼叫或高优先级GCM消息才能将其唤醒。但是像WhatsApp一样,在打瞌睡模式下,它会在2小时或更长时间后收到消息,这取决于计时器。但有一个名为“白名单”的“未优化”应用程序列表,您可以在其中手动添加应用程序 好的,我想找到一种方法,以编程方式将我的应用程序

这个问题与Android 6.0预览版3有关,它将于本月底最终发布

我正在Nexus5“锤头”上的谷歌预览版3中测试Android 6.0中的一些东西

新功能是“打瞌睡模式”——类似于深度睡眠模式,当网络被禁用且手机处于睡眠状态时,只有短信、呼叫或高优先级GCM消息才能将其唤醒。但是像WhatsApp一样,在打瞌睡模式下,它会在2小时或更长时间后收到消息,这取决于计时器。但有一个名为“白名单”的“未优化”应用程序列表,您可以在其中手动添加应用程序

好的,我想找到一种方法,以编程方式将我的应用程序添加到“白名单应用程序列表”中,该列表存在于设备的电池设置中,无需用户交互

试图使用反射进入其中,我发现:

在android.os.IDeviceIdleController中有一种方法:

公共摘要void addPowerSaveWhitelistApp(字符串packageNameOfApp)

但这是一个界面。。。因此,我们不能创建接口的实例

目前还没有关于此接口、方法或任何继承树的文档

也许你知道我应该在哪里寻找以编程方式将我的应用程序添加到那里的可能性

还有一种方法

公共抽象布尔值isPowerSaveWhitelistApp(字符串packageName)

我认为应该可以以某种方式访问它?!检查该应用程序是否存在于白名单中,并可能在最后要求用户将其添加到白名单中

所以我的问题是,你们有没有人试着做一些效果更好的东西??因为我被困住了,我认为这是一条死胡同


欲了解更多信息:

如果没有Android M preview 3上的用户交互,则无法禁用电池优化(=用于瞌睡模式的白名单应用程序)

可以通过以下方式进行用户交互:

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);

据我所知,你不能把自己从睡梦中列入白名单。忽略电池优化不会禁用doze。请看这里: 更新:在M的发行版中,您可以请求忽略电池优化,这至少会让您在打瞌睡时正常访问互联网。

UPDATE 当设备再次处于静止状态,屏幕关闭并打开电池一段时间后,Doze会对PowerManager.WakeLock、AlarmManager警报和GPS/Wi-Fi扫描应用完整的CPU和网络限制

请访问以了解更多详细信息

下表突出显示了请求或响应的可接受用例 在电池优化例外白名单上。一般来说 您的应用程序不应在白名单上,除非是Doze或app Standby 破坏应用程序的核心功能或有技术原因 您的应用程序无法使用GCM高优先级消息

打盹特别可能影响AlarmManager报警和计时器管理的活动,因为当系统处于打盹状态时,Android 5.1(API级别22)或更低版本中的报警不会触发

Android 6.0(API级别23)引入了两种新的AlarmManager方法:
setAndAllowHileId()
setExactAndAllowHileId()
。使用这些方法,您可以设置即使设备处于休眠状态也会触发的警报

注意:无论是
设置和AllowHileIDLE()
还是
设置ExactAndAllowHileIDLE()
都不能在每个应用程序中每15分钟触发一次以上的警报

添加权限

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

白名单可以通过编程方式完成。 要在白名单应用程序中添加设备,请从应用程序运行以下命令:

adb shell dumpsys deviceidle whitelist +<package_name>
adb shell dumpsys deviceidle whitelist -<package_name>
adb外壳转储系统设备白名单+
要从白名单应用程序中删除设备,请从应用程序中运行以下命令:

adb shell dumpsys deviceidle whitelist +<package_name>
adb shell dumpsys deviceidle whitelist -<package_name>
adb外壳转储系统设备白名单-

我认为这个助手类应该满足您的所有需求

要使用它请求操作系统将您的应用程序列入白名单,您可以使用PrepareIntentForWhiteListingOffbatteryOptimization。如果您得到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;
    }


}
公共类PowerSaverHelper{
公共枚举PowerSaveState{
打开、关闭、错误\u获取\u状态、不相关\u旧的\u ANDROID\u API
}
公共枚举白名单电池优化{
白名单,未白名单,错误获取状态,未知太旧ANDROID API检查,无关旧ANDROID API
}
公共枚举状态{
正常交互、打瞌睡、打开空闲、正常非交互、错误获取状态、不相关的旧ANDROID API、未知的旧ANDROID API供检查
}
@非空
公共静态DozeState getDozeState(@NonNull上下文){
if(VERSION.SDK\u INT