Doze 模式下 Alram 无法定时唤醒的解决方案

2024-02-09 20:32

本文主要是介绍Doze 模式下 Alram 无法定时唤醒的解决方案,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. adb 命令模拟进入doze模式

  1. 设置未充电状态

方便连接logcat查看实时日志,正常情况下如果连接 USB 是无法进入doze模式,这个步骤是欺骗系统当前没有连接USB,虽然实际连接得好好的

adb shell dumpsys battery unplug
  1. 设置开启 alarm 日志

并不是每台机器都开启 alarm 的日志,所以我们可以命令强制开启

adb shell dumpsys alarm log on
  1. 强制进入Doze模块

要调试就进入深度休眠模式,即 deep idle mode

adb shell dumpsys deviceidle force-idle deep

2. 复现现象

2.1 Alarm的参考代码
    starAlarmTaskByService(this, 5);public static void starAlarmTaskByService(Context context, int intervalMinute) {AlarmManager mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);long triggerAtMillis = System.currentTimeMillis() + (intervalMinute * 60 * 1000);Log.d(TAG, "starAlarmTaskByService action = " + ACTION_RTC_WAKEUP_ALRTM_TYPE_0_SERVIE  + ", 下次唤醒时刻 = " + DateTimeUtil.getSysDate(triggerAtMillis));Intent intent = new Intent(context, MyService.class);intent.setAction(ACTION_RTC_WAKEUP_ALRTM_TYPE_0_SERVIE);PendingIntent operation = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {mAlarmManager.setExact(AlarmManager.RTC_WAKEUP, triggerAtMillis, operation);} else {mAlarmManager.set(AlarmManager.RTC_WAKEUP, triggerAtMillis, operation);}}
2.2 异常日志

注意这里的 flags

2018-08-23 14:25:07.989 934-24435/? V/AlarmManager: set(PendingIntent{c4c0513: PendingIntentRecord{59c2350 test.demo.alarm.zui.com.alarmtest startService}}) : type=0 triggerAtTime=1535005807985 win=0 tElapsed=70204635 maxElapsed=70204635 interval=0 flags=0x1(非DeviceIdleUserWhitelist白名单)
2.3 正常日志

注意这里的 flags

2018-08-23 14:18:29.063 934-945/? V/AlarmManager: set(PendingIntent{c6e22ba: PendingIntentRecord{f55a56b test.demo.alarm.zui.com.alarmtest startService}}) : type=0 triggerAtTime=1535005409060 win=0 tElapsed=69805710 maxElapsed=69805710 interval=0 flags=0x9(DeviceIdleUserWhitelist白名单正常)
2.4 查看对应doze模式白名单

使用命令 adb shell dumpsys deviceidle whitelist 查看

2.4.1 异常现象白名单 1

这个是在系统源码路径 frameworks\base\data\etc\platform.xml,可以手机系统用 adb shell cat “/etc/permissions/platform.xml”查看

D:\AndroidStudioProjects>adb shell dumpsys deviceidle whitelist
system-excidle,com.android.providers.downloads,10020
system-excidle,com.android.shell,2000
system,com.android.providers.downloads,10020
system,com.android.shell,2000
system,test.demo.alarm.zui.com.alarmtest,10090
2.4.2 异常现象白名单 2

这里是没有任何设置白名单

D:\AndroidStudioProjects>adb shell dumpsys deviceidle whitelist
system-excidle,com.android.providers.downloads,10020
system-excidle,com.android.shell,2000
system,com.android.providers.downloads,10020
system,com.android.shell,2000
2.4.3 正常现象的白名单

这里是使用软件接口进行配置 mDeviceIdleService.addPowerSaveWhitelistApp(pkg);

D:\AndroidStudioProjects>adb shell dumpsys deviceidle whitelist
system-excidle,com.android.providers.downloads,10020
system-excidle,com.android.shell,2000
system,com.android.providers.downloads,10020
system,com.android.shell,2000
user,test.demo.alarm.zui.com.alarmtest,10090

3. 相关源码

根据 mDeviceIdleUserWhitelist 进行对应的 flags 的重新设置,这个mDeviceIdleUserWhitelist是使用接口进行加入

    private final IBinder mService = new IAlarmManager.Stub() {@Overridepublic void set(String callingPackage,int type, long triggerAtTime, long windowLength, long interval, int flags,PendingIntent operation, IAlarmListener directReceiver, String listenerTag,WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock) {...省略// If the caller is a core system component or on the user's whitelist, and not calling// to do work on behalf of someone else, then always set ALLOW_WHILE_IDLE_UNRESTRICTED.// This means we will allow these alarms to go off as normal even while idle, with no// timing restrictions.} else if (workSource == null && (callingUid < Process.FIRST_APPLICATION_UID|| callingUid == mSystemUiUid|| Arrays.binarySearch(mDeviceIdleUserWhitelist,UserHandle.getAppId(callingUid)) >= 0)) {flags |= AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;flags &= ~AlarmManager.FLAG_ALLOW_WHILE_IDLE;}setImpl(type, triggerAtTime, windowLength, interval, operation, directReceiver,listenerTag, flags, workSource, alarmClock, callingUid, callingPackage);}

4.解决方案

使用软件接口设置doze模式白名单,解决即可,这样就可以开心的准时接收消息了

  • 核心接口 mDeviceIdleService.addPowerSaveWhitelistApp(pkg);
/** Copyright (C) 2015 The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**      http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/
package com.android.sufadi.powersave.util;import android.os.IDeviceIdleController;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.ArraySet;
import android.util.Log;/*** Handles getting/changing the whitelist for the exceptions to battery saving features.*/
public class PowerWhitelistBackend {private static final String TAG = "LavaPowerWhitelistBackend";private static final String DEVICE_IDLE_SERVICE = "deviceidle";private static final PowerWhitelistBackend INSTANCE = new PowerWhitelistBackend();private final IDeviceIdleController mDeviceIdleService;private final ArraySet<String> mWhitelistedApps = new ArraySet<>();private final ArraySet<String> mSysWhitelistedApps = new ArraySet<>();public PowerWhitelistBackend() {mDeviceIdleService = IDeviceIdleController.Stub.asInterface(ServiceManager.getService(DEVICE_IDLE_SERVICE));refreshList();}public int getWhitelistSize() {return mWhitelistedApps.size();}public boolean isSysWhitelisted(String pkg) {return mSysWhitelistedApps.contains(pkg);}public boolean isWhitelisted(String pkg) {return mWhitelistedApps.contains(pkg);}public void addApp(String pkg) {try {mDeviceIdleService.addPowerSaveWhitelistApp(pkg);mWhitelistedApps.add(pkg);} catch (RemoteException e) {Log.w(TAG, "Unable to reach IDeviceIdleController", e);}}public void removeApp(String pkg) {try {mDeviceIdleService.removePowerSaveWhitelistApp(pkg);mWhitelistedApps.remove(pkg);} catch (RemoteException e) {Log.w(TAG, "Unable to reach IDeviceIdleController", e);}}private void refreshList() {mSysWhitelistedApps.clear();mWhitelistedApps.clear();try {String[] whitelistedApps = mDeviceIdleService.getFullPowerWhitelist();for (String app : whitelistedApps) {mWhitelistedApps.add(app);}String[] sysWhitelistedApps = mDeviceIdleService.getSystemPowerWhitelist();for (String app : sysWhitelistedApps) {mSysWhitelistedApps.add(app);}} catch (RemoteException e) {Log.w(TAG, "Unable to reach IDeviceIdleController", e);}}public static PowerWhitelistBackend getInstance() {return INSTANCE;}}

这篇关于Doze 模式下 Alram 无法定时唤醒的解决方案的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/695208

相关文章

线上Java OOM问题定位与解决方案超详细解析

《线上JavaOOM问题定位与解决方案超详细解析》OOM是JVM抛出的错误,表示内存分配失败,:本文主要介绍线上JavaOOM问题定位与解决方案的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录一、OOM问题核心认知1.1 OOM定义与技术定位1.2 OOM常见类型及技术特征二、OOM问题定位工具

Python一次性将指定版本所有包上传PyPI镜像解决方案

《Python一次性将指定版本所有包上传PyPI镜像解决方案》本文主要介绍了一个安全、完整、可离线部署的解决方案,用于一次性准备指定Python版本的所有包,然后导出到内网环境,感兴趣的小伙伴可以跟随... 目录为什么需要这个方案完整解决方案1. 项目目录结构2. 创建智能下载脚本3. 创建包清单生成脚本4

java.sql.SQLTransientConnectionException连接超时异常原因及解决方案

《java.sql.SQLTransientConnectionException连接超时异常原因及解决方案》:本文主要介绍java.sql.SQLTransientConnectionExcep... 目录一、引言二、异常信息分析三、可能的原因3.1 连接池配置不合理3.2 数据库负载过高3.3 连接泄漏

Linux下MySQL数据库定时备份脚本与Crontab配置教学

《Linux下MySQL数据库定时备份脚本与Crontab配置教学》在生产环境中,数据库是核心资产之一,定期备份数据库可以有效防止意外数据丢失,本文将分享一份MySQL定时备份脚本,并讲解如何通过cr... 目录备份脚本详解脚本功能说明授权与可执行权限使用 Crontab 定时执行编辑 Crontab添加定

C#文件复制异常:"未能找到文件"的解决方案与预防措施

《C#文件复制异常:未能找到文件的解决方案与预防措施》在C#开发中,文件操作是基础中的基础,但有时最基础的File.Copy()方法也会抛出令人困惑的异常,当targetFilePath设置为D:2... 目录一个看似简单的文件操作问题问题重现与错误分析错误代码示例错误信息根本原因分析全面解决方案1. 确保

C# LiteDB处理时间序列数据的高性能解决方案

《C#LiteDB处理时间序列数据的高性能解决方案》LiteDB作为.NET生态下的轻量级嵌入式NoSQL数据库,一直是时间序列处理的优选方案,本文将为大家大家简单介绍一下LiteDB处理时间序列数... 目录为什么选择LiteDB处理时间序列数据第一章:LiteDB时间序列数据模型设计1.1 核心设计原则

SpringBoot3匹配Mybatis3的错误与解决方案

《SpringBoot3匹配Mybatis3的错误与解决方案》文章指出SpringBoot3与MyBatis3兼容性问题,因未更新MyBatis-Plus依赖至SpringBoot3专用坐标,导致类冲... 目录SpringBoot3匹配MyBATis3的错误与解决mybatis在SpringBoot3如果

C++ vector越界问题的完整解决方案

《C++vector越界问题的完整解决方案》在C++开发中,std::vector作为最常用的动态数组容器,其便捷性与性能优势使其成为处理可变长度数据的首选,然而,数组越界访问始终是威胁程序稳定性的... 目录引言一、vector越界的底层原理与危害1.1 越界访问的本质原因1.2 越界访问的实际危害二、基

Python Flask实现定时任务的不同方法详解

《PythonFlask实现定时任务的不同方法详解》在Flask中实现定时任务,最常用的方法是使用APScheduler库,本文将提供一个完整的解决方案,有需要的小伙伴可以跟随小编一起学习一下... 目录完js整实现方案代码解释1. 依赖安装2. 核心组件3. 任务类型4. 任务管理5. 持久化存储生产环境

C#和Unity中的中介者模式使用方式

《C#和Unity中的中介者模式使用方式》中介者模式通过中介者封装对象交互,降低耦合度,集中控制逻辑,适用于复杂系统组件交互场景,C#中可用事件、委托或MediatR实现,提升可维护性与灵活性... 目录C#中的中介者模式详解一、中介者模式的基本概念1. 定义2. 组成要素3. 模式结构二、中介者模式的特点