如何应对 Android 面试官 -> 电量如何优化?

前言


本章主要讲解下『电量』如何优化;

Doze 低电耗模式


低电耗模式针对的是『系统』行为;

如果设备未充电,屏幕熄灭,让设备在一段时间内保持不活动状态,设备就会处于 doze 模式,从而延迟应用的后台 CPU 和网络活动,从而降低耗电量;

在低电耗模式下,系统有些功能是不可用的;

  • 暂停网络访问;
  • 系统忽略 PowerManager.WakeLock 唤醒锁定【Wakelock 可以唤醒设备CPU,也就是说设备CPU不会被唤醒了,也可以唤醒屏幕,保持屏幕长亮】;
  • AlarmManager 闹钟推迟到下一个维护期;
    • 如果需要设置在设备处于低电耗模式时触发的闹钟,请使用 API 23(6.0) 提供的 setAndAllowWhileIdle() (一次性闹钟,同set方法)或 setExactAndAllowWhileIdle() (比set方法设置的精度更高,同setExact)
    • 使用 setAlarmClock() 设置的闹钟将继续正常触发,系统会在这些闹钟触发之前不久退出低电耗模式
  • 系统不执行 WLAN 扫描;
  • 系统不允许运行同步适配器AbstractThreadedSyncAdapter (账号同步拉活);
  • 系统不允许运行 JobScheduler;

StandBy 待机模式


待机模式针对的是『应用』行为;

当用户在一段时间内未触摸应用,并且应用没有以下表现的时候,Android 系统就会使应用进入 Stand By 模式;

但是以下几种情况除外,不会使应用进入待机模式

  • 用户明确应用启动;
  • 应用当前有一个进程在前台运行;
  • 应用生成用户可在锁定屏幕或通知栏中看到的通知;
  • 当用户将设备插入电源时,系统会从待机状态释放应用;

如何让应用跳出待机模式

  • 延迟用户近期未与之交互的应用的后台网络活动
  • 获取充电状态,进行业务的处理,来降低耗电量;
  • 应用加入白名单
    • 跳转系统设置页面,让用户自行选择加入 startActivity(new Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS));
    • 弹出对话框,让用户选择 还是 拒绝 Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); intent.setData(Uri.parse("package:"+getPackageName())); startActivity(intent);

WorkManager


一个针对原有的 Android 后台调度 API 整合的组件; 当应用进入后台之后,帮助我们更简单的完成一些约束条件的工作;

如何使用

约束条件 + 后台任务

App 层面电量监控


Java Hook

可以从 WakeLock,Alarm、GPS、Sensor 等角度来实现电量的监控

WakeLock

WakeLock 用来阻止 CPU、屏幕甚至是键盘的休眠,保证任务在灭屏的时候可以被正确执行,可以让应用有控制AP是否休眠。类似 Alarm、JobService 也会申请 WakeLock 来完成后台 CPU 操作。WakeLock 的核心控制代码都在 PowerManagerService 中,实现的方法非常简单;

如何使用:

ini 复制代码
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WeakLock weakLock = powerManager.newWeakLock(ON_AFTER_RELEASE | PARTIAL_WEAK_LOCK, "Tag");

// onResume 中获取
weakLock.acquire();

// onPause 中释放
weakLock.release();

然后,我们来执行 adb 命令抓取相关信息

arduino 复制代码
adb shell dumpsys "power | grep -i wake"

这个 adb 命令可以用来抓取一些电量信息;

借助这些信息,通过 battry historian 可以查看申请了几次,如果申请的特别频繁,那么就会耗电的问题;

Hook 逻辑 动态代理获取两个接口的调用,用来实现电量的监控

Alarm

Alarm 用来做一些定时的重复任务,它一共有四个类型,其中 ELAPSED_REALTIME_WAKEUP 和 RTC_WAKEUP 类型都会唤醒设备。同样,Alarm 的核心控制逻辑都在 AlarmManagerService 中;

同样也是通过 动态代理 的方式来实现 hook 逻辑

插桩

基础类中 进行插桩处理

Facebook 也有一个耗电监控的开源库 Battery-Metrics

耗电检测 Battery Historian


如何进行耗电检测,我们来深度探讨下~

Battery Historian 是一个可以了解设备随时间的耗电情况的工具 。在系统级别,该工具以 HTML 的形式可视化来自系统日志的电源相关事件。在具体应用级别,该工具可提供各种数据,帮助您识别耗电的应用行为;

安装教程

安装教程,这里可以直接看这个安装教程链接 电量优化Battery Historian2.0 配置

数据收集

  1. 第一步:重置电池数据收集 adb shell dumpsys batterystats --reset
  2. 开启wakeLock唤醒锁信息记录(可选) adb shell dumpsys batterystats --enable full-wake-history
  3. 断开设备与计算机的连接,以便仅消耗设备电池的电量 (注意:这个过程最少持续一个小时的时间);
  4. 使用您的应用并执行您想要获取数据的操作;例如,断开 WLAN 连接并将数据发送到云端
  5. 重新连接手机;
  6. 生成报告
    • 对于搭载 Android 7.0 及更高版本的设备 adb bugreport > [path/]bugreport.zip
    • 对于搭载 Android 6.0 及更低版本的设备 adb bugreport > [path/]bugreport.txt
  7. 关闭wakeLock统计:adb shell dumpsys batterystats --disable full-wake-history

启动 Battery Historian

启动起来之后,就是这样的一个界面,然后将我们上面收集的日志信息上传给 Battry Historian;

上传成功之后,会出现下面这样的一个界面;

图中的黑线就代表着我们的一个耗电情况;

查看具体应用的数据

表格提供了关于您的应用的两个数据维度。首先,您可以查找应用的耗电量与其他应用相比的排名位置。为此,请 点击"Tables"下的"Device Power Estimates"表格。

根据耗电排名具体问题,具体分析即可;

好了,电量优化就写到这里吧

欢迎三连


来都来了,点个关注,点个赞吧,你的支持是我最大的动力~

相关推荐
一只叫煤球的猫38 分钟前
你真的会用 return 吗?—— 11个值得借鉴的 return 写法
java·后端·代码规范
CYRUS_STUDIO1 小时前
使用 Dex2C 加壳保护 Android APK 代码
android·安全·逆向
颇有几分姿色1 小时前
Spring Boot 读取配置文件的几种方式
java·spring boot·后端
爱编程的鱼1 小时前
C# 枚举(Enum)声明与使用详解
java·windows·c#
人生导师yxc1 小时前
Spring MVC
java·spring·mvc
曹牧1 小时前
Java 调用webservice接口输出xml自动转义
java·开发语言·javascript
字节王德发1 小时前
如何在SpringBoot中通过@Value注入Map和List并使用YAML配置?
java·maven·intellij-idea
@淡 定1 小时前
Spring Boot 的配置加载顺序
java·spring boot·后端
龙大大L1 小时前
第五章:5.3 ESP32物联网应用:阿里云IoT平台与腾讯云IoT平台的数据上传与远程控制
java·物联网·struts·esp32
alexhilton2 小时前
理解Jetpack Compose中副作用函数的内部原理
android·kotlin·android jetpack