【问题标题】:How to WhiteList app in Doze mode Android 6.0如何在打盹模式下将应用列入白名单 Android 6.0
【发布时间】:2015-12-14 03:30:52
【问题描述】:

此问题与将于本月底最终发布的 Android 6.0 Preview 3 有关。

我正在 Nexus 5“锤头”上的 Google 预览版 3 中测试 Android 6.0 中的一些内容。

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

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

尝试使用反射进入我发现:

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

public abstract void addPowerSaveWhitelistApp(String packageNameOfApp)

但这是一个接口……所以我们不能创建接口的实例。

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

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

还有一种方法

public abstract boolean isPowerSaveWhitelistApp (String packageName)

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

所以我的问题是,你们有没有人尝试过做出更好的结果?因为我被困住了,我认为这是一个死胡同。

更多信息:https://newcircle.com/s/post/1739/2015/06/12/diving-into-android-m-doze

【问题讨论】:

    标签: java android preview android-6.0-marshmallow


    【解决方案1】:

    在 Android M 预览版 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);
    

    【讨论】:

    • 您如何定义设置?我的 IDE 以某种方式找不到 Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS ......找到了。好的。现在开始测试:)
    • 参见此处:stackoverflow.com/questions/32316491/… 虽然人们不赞成我的评论,但它实际上是正确的(在 Android M 预览版 3 上测试)。
    • 我们必须在哪里编写这段代码? (Intent intent = new Intent(); ------- context.startActivity(intent)?
    • 如果pm.isIgnoringBatteryOptimizations(packageName)true 为什么要再次请求?
    • @androiddeveloper 打盹模式是在 Android 6 API 23 中引入的,因此早期的 Android 版本没有打盹模式,因此不需要解决方法。
    【解决方案2】:

    据我所知,您不能将自己从 Doze 中列入白名单。忽略电池优化不会禁用打盹。见这里:https://code.google.com/p/android-developer-preview/issues/detail?id=2225 更新:在 M 的发布版本中,您可以请求忽略电池优化,这至少可以让您在打盹模式下正常访问互联网。

    【讨论】:

    • 仅供参考,我已经对此进行了多次测试。 setexactallowwhileidle 警报只能每 15 分钟触发一次,无论是否启用忽略电池优化。
    • 更新:在发布版本中,忽略优化会影响打瞌睡时的网络访问。
    【解决方案3】:

    更新

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

    访问Use Cases for Whitelisting了解更多详情。

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

    android n developer

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

    Android 6.0(API 级别 23)引入了两个新的 AlarmManager 方法:setAndAllowWhileIdle()setExactAndAllowWhileIdle()。使用这些方法,您可以设置即使设备处于打瞌睡状态也会触发的警报。

    注意setAndAllowWhileIdle()setExactAndAllowWhileIdle() 在每个应用程序中每 15 分钟发出一次警报都不能超过一次。

    Testing with Doze and App Standby

    【讨论】:

    • 两种AlarmManager 方法都不起作用。也许取决于设备,在华为 Ascend Mate 7 上,这些方法失败并且不执行。另外,如果时间超过 15 分钟....Android Bug?
    • 根据 developer.android.com 发布的版本,请检查设备是否有 android-m,这将起作用,但会应用注释。
    • 感谢您的“提示”,但我很确定 MM 已安装 :) ...这也可能是华为的行为。华为在他们的设备上实施了自己的节能管理器。这里正在运行 MM 和华为的能源管理系统。我认为他们互相咬。我已将我的应用程序设置为白名单、保护它以及所有其他可能的设置,以确保它保持活动状态。没有任何效果。也联系过华为,但还是没有得到答复......
    • 很高兴它对您有所帮助。谢谢你的赞赏。
    • 我和一个朋友谈过,用的是 LG Nexus(不完全了解型号)......在这里它可以工作。但问题是,我认为这与设备无关,网络连接将被暂停。文档中指出了这一点。如果是这样,那么很多聊天应用程序如果不使用 GCM 就会出现问题。很伤心.....
    【解决方案4】:

    添加权限

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

    请求将您的应用列入白名单

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

    【讨论】:

    • 感谢您的回答。此方法要求用户允许或拒绝,我正在允许该权限,但不确定它是否忽略电池优化,因为如果我手动检查设置,即使我允许该权限也不会更改任何内容。谁能澄清一下?
    • 这可能会完成工作。但是,如果您这样做,您的应用将不被 Play 商店接受发布。 Android Studio 会给你一个警告。 Suggested reading
    • @Kathir 请看Acceptable use cases for whitelisting > developer.android.com/training/monitoring-device-state/…
    • 那么,白名单需要多长时间?它会立即将应用列入白名单吗?
    • 别这样,修改fcm参数让它出现
    【解决方案5】:

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

    adb shell dumpsys deviceidle whitelist +<package_name>
    

    要从白名单应用程序中删除设备,请从应用程序运行以下命令:

    adb shell dumpsys deviceidle whitelist -<package_name>
    

    【讨论】:

    • 不确定这是否真的需要root。据我所知,我的手机没有root,但上面的命令有效。
    • 您能解释一下这是如何工作的吗?这里有点糊涂。这是否仅适用于特定设备的白名单,或者我可以使用运行应用程序的任何设备来实现这一点?
    • 如果您通过代码运行此命令,它将尝试在每部手机上运行
    • 我们必须每次运行这个命令还是安装后只运行一次就够了?
    • 即使您的应用程序被杀死,这个救命的答案也可以运行您的前台服务
    【解决方案6】:

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

    要使用它来请求操作系统将您的应用列入白名单,您可以使用 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;
        }
    
    
    }
    

    【讨论】:

    • 我已经尝试过解决方案,用小米测试过,即使我能够从省电模式中删除应用程序,FCM 也不起作用,我知道这不是您的解决方案的问题,您解决方案完美地检测了模式,但是你能帮忙吗?我有点像被困在这一刻了。
    • @Sanoop 抱歉,我已经继续前进了。
    • @SanoopSurendran,中国房间需要授予其他权限,不仅仅是打瞌睡
    猜你喜欢
    • 2017-05-19
    • 1970-01-01
    • 1970-01-01
    • 2018-03-22
    • 2020-09-24
    • 1970-01-01
    • 2015-10-14
    • 2013-07-26
    • 1970-01-01
    相关资源
    最近更新 更多