Android 性能优化:08.耗电优化

一、耗电原理

1. 硬件维度

  • 屏幕:通常是第一大头,尤其是高亮度、高刷新率、亮色界面(OLED 上白底明显更耗电)。
  • CPU/GPU:持续高负载计算、复杂渲染、编解码。
  • 蜂窝基带(Modem/Radio) :App 侧可控的最大头之一。蜂窝电台有状态机:激活(Full Power)→ 低功耗(Low Power)→ 空闲(Standby),每次唤醒电台传输后都有数秒"尾巴时间(tail time)"保持高功耗 。这意味着 10 次分散的小请求远比合并成 1 次大请求耗电------这是网络优化的理论基础。
  • GPS/定位芯片:持续高精度定位非常耗电。
  • 传感器:加速度、陀螺仪持续采样;摄像头、麦克风、扬声器、震动马达耗电也较大。

2. 软件维度

  • 持有 WakeLock 不放,CPU 无法休眠(手机发烫、待机一晚掉电 20% 的元凶)。
  • 频繁 Alarm/轮询/定时器 唤醒系统。
  • 后台持续定位、持续网络心跳。
  • 不可见页面仍在跑动画、轮播图、视频解码、JS 定时器。
  • 频繁 I/O 写盘(日志、埋点逐条上报)。

二、测量与归因:先测,再优化

耗电优化最大的坑是"凭感觉改"。标准流程:控制变量 → 清状态 → 跑场景 → 导出分析

工具 用途
dumpsys batterystats + Battery Historian 整机级归因:看谁持有 WakeLock、谁频繁唤醒、谁的网络/定位/传感器时长长。核心武器
Android Studio Profiler / Power Profiler App 级实时查看 CPU、网络、定位等能耗事件(部分 Pixel 机型可读功耗导轨数据)
dumpsys alarm / dumpsys jobscheduler 检查自家闹钟、Job 是否被过度调度、是否被系统限频
Perfetto 抓取系统级 trace,分析唤醒源、CPU 频率
Android Vitals(Play Console) 线上指标:excessive wakeups、stuck partial wake locks、excessive background network usage------直接影响商店推荐权重

实操套路:

bash 复制代码
adb shell dumpsys batterystats --reset   # 清空统计
adb shell dumpsys batterystats --enable full-wake-history
# 断开 USB(否则在充电数据不准),跑 30~60 分钟目标场景
adb bugreport bugreport.zip              # 导出后拖进 Battery Historian 分析

关注自家包名下的:Wakelock 持有次数与总时长、Alarm 唤醒次数、移动网络/WiFi 活跃时长、GPS 使用时长、CPU 各频率段占用。

线上再叠加自建监控:充电状态、前后台时长、各类任务调度次数的埋点聚合,灰度对比耗电指标。


三、顺着系统机制走

  1. Doze 模式(Android 6+) :息屏+静止一段时间后,系统推迟网络、Job、闹钟,进入维护窗口。你的任务应该主动适配,而不是对抗。
  2. App Standby Buckets(Android 9+) :系统把应用分进 active / working_set / frequent / rare / restricted 桶,越不活跃,Job、网络、FCM 高优先级消息配额越少。保住活跃度的正道是用户真的常用,而不是保活。
  3. 后台执行限制(Android 8+):后台不能随意起 Service,隐式广播静态注册被禁。
  4. 前台服务(FGS)收紧 :Android 12 限制后台启动 FGS;Android 14 必须声明 foregroundServiceType;Android 15 对 dataSync 等类型加了每日时长上限。
  5. 精确闹钟 :Android 12+ 需 SCHEDULE_EXACT_ALARM 权限,且 Play 商店会审核------非闹钟类 App 滥用直接拒审。
  6. 省电模式 :用户开启后系统限网络、限后台。可用 PowerManager.isPowerSaveMode() 感知并主动降级(降帧、停预加载)。

一句话:系统给了统一的任务合并管道(JobScheduler/WorkManager/FCM),你越用它,越省电;越绕过它(自研保活、长轮询),越耗电且被惩罚。


四、分模块优化方法

1. 网络优化

  • 合并与批处理(batching):埋点、日志攒批量上报;多个小接口合并;设置"传输窗口"集中收发。
  • 消灭轮询 :用 FCM/长连接推送替代定时拉取;必须轮询时用指数退避拉长间隔。
  • 挑时机 :大文件下载/预加载只在 WiFi + 充电 时做:
kotlin 复制代码
val request = OneTimeWorkRequestBuilder<SyncWork>()
    .setConstraints(
        Constraints.Builder()
            .setRequiredNetworkType(NetworkType.UNMETERED)  // WiFi/不限流量
            .setRequiresCharging(true)
            .build()
    ).build()
  • 减少传输量:gzip、Protobuf、差量同步、图片按需分辨率、HTTP 缓存(ETag/Cache-Control)。
  • 及时断开:长连接空闲超时收短、页面销毁关 WebSocket。

2. 定位优化

  • FusedLocationProviderClient,别直接怼 GPS Provider。
  • 精度够用就好 :能用 PRIORITY_BALANCED_POWER_ACCURACY(基站/WiFi)就不用 HIGH_ACCURACY
  • 批量定位setMaxWaitTime() 让系统攒一批位置一起回调,硬件可以休眠更久。
  • Geofencing 替代持续定位:围栏场景耗电差一个数量级。
  • 进入后台/离开页面立即 removeLocationUpdates;后台定位本身受系统限频(每小时几次)。

3. 传感器

  • 按场景选采样率(SENSOR_DELAY_NORMAL 别用 FASTEST)。
  • 利用 FIFO batching (registerListener(listener, sensor, rate, maxReportLatencyUs))批量上报。
  • 页面 onPause 必须 unregisterListener------这是最常见的漏电点。

4. 唤醒与任务调度

  • WakeLock :App 层基本不该手动持有;必须用就带超时 acquire(10*60*1000L),并在 finally 里 release()。排查"stuck partial wake lock"用 Historian 一抓一个准。
  • AlarmManager :能模糊就别精确(set/setWindow/setInexactRepeating 替代 setExact);非时钟类功能别申请精确闹钟权限。
  • 统一用 WorkManager/JobScheduler 收口 :它们会把多个任务合并到系统维护窗口批量执行,是省电的关键杠杆。建一个"任务调度中心",禁止业务方各自起 Timer/Handler.postDelayed 轮询。
  • 清理冗余组件 :取消不再需要的 Job/Alarm;检查静态注册的广播(网络变化等)并改为动态注册或 JobScheduler 网络约束触发。

5. UI、动画与屏幕

  • 不可见即停 :页面滑出屏幕,立即停动画、停视频解码、停轮播定时器、停 ValueAnimator;RecyclerView 离屏 item 释放播放器。监听生命周期统一收口。
  • 深色模式:OLED 屏幕上黑像素几乎不发光,实测可省 15%~40% 屏幕功耗(亮度越高省得越多)。这是"免费"的省电功能,还顺了用户体验。
  • 帧率适配:视频、阅读等场景主动降帧,别全程顶 120Hz:
kotlin 复制代码
surface.setFrameRate(30f, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT)
// 或 Window 级:attributes.preferredFrameRate / preferredDisplayModeId
  • 减少过度绘制、扁平化布局:降低 GPU 负载间接省电。
  • 亮度敏感场景(相机取景、视频)才申请 keepScreenOn,用完即撤。

6. WebView 与第三方 SDK

  • WebView 里的 JS 定时器、CSS 动画、长轮询 在页面不可见时仍在烧电:onPausewebView.onPause()/pauseTimers()(注意是全局生效),不可见时 stopLoading
  • 三方 SDK 是耗电大户:推送、统计、广告、风控 SDK 各自有心跳和定位逻辑。治理手段:接入前做耗电评测(Historian 归因到 SDK 进程)、能聚合就聚合(厂商通道聚合推送)、延迟初始化、无用 SDK 坚决下线。
  • 广告 SDK:限制刷新频率,离屏销毁。

7. 存储与计算

  • SharedPreferencesapply() 不用 commit();配置项合并写。
  • SQLite 批量写入必须包事务(逐条 insert 触发大量磁盘 I/O 和 fsync)。
  • 日志:控制级别、合并写盘、批量上传,release 包关 debug 日志。
  • 计算:避免高频 GC(对象池、复用 buffer)、选对数据结构、JSON 选高效解析库;耗时任务移到子线程不只是流畅性问题------CPU 更快干完活就能更快回到低功耗档(race to idle),本身也是省电。

8. 其他零散但真实有效的点

  • 震动、铃声、闪光灯提醒做节流。
  • 相机 Camera 对象页面不可见立即释放。
  • 蓝牙扫描用 SCAN_MODE_LOW_POWER,及时停止。

五、流程与治理

  1. 门禁:CI 上跑固定场景的耗电回归(控制变量:同款机型、飞行模式+指定 WiFi、固定亮度),指标劣化阻断合入。
  2. 线上监控:Android Vitals 三项电量指标设告警;自建"待机一晚掉电率"用户反馈通道。
  3. 归因文化:任何耗电投诉先用 Historian 归因到模块,再动手;杜绝"玄学省电"。
  4. 常见误区提醒 :
    • ❌ 双进程守护、全家桶拉活------省电反效果,还招 Vitals 惩罚和应用商店管控;
    • ❌ 1 秒级 Handler 轮询做倒计时------用 Chronometer 或事件驱动;
    • ❌ 为防 Doze 加白名单引导------只对闹钟类等极少数场景合理,滥用影响口碑。

六、检验列表

  • Historian 无自家长持 WakeLock、无高频唤醒
    -无自研轮询,后台任务全部走 WorkManager
  • 大数据传输有 WiFi/充电约束
  • 定位/传感器在 onPause 全部注销
  • 不可见页面停动画、停视频、停 JS
  • 深色模式已适配,视频场景已降帧
  • 埋点日志批量上报,DB 批量写入带事务
  • 三方 SDK 做过耗电归因评测
  • Vitals 三项电量指标达标且有告警
相关推荐
五仁烧饼31 分钟前
Unity性能优化系列内存篇 - 移动端内存优化
unity·性能优化·游戏引擎
Kapaseker41 分钟前
Compose SelectionState API — 主动控制文本选择
android·kotlin
拾光Ծ2 小时前
【MySQL】对表数据的操作:增删查改(CRUD)
android·数据库·sql·mysql
一笑的小酒馆12 小时前
Android中的tcp通信
android
默阳123415 小时前
2026年Android中高级面试题专栏(Android进阶篇)
android
古法安卓16 小时前
Android-日志系统源码解析
android·java·android studio
恋猫de小郭17 小时前
Android 17 + OkHttp 5.5.0 ,全新 ECH 下你的 HTTPS 域名可以请求时被安全隐藏
android·前端·flutter
小强闯江湖17 小时前
不只是让 AI 写代码:ViewCompose 把 Android UI 做成了可编译、可渲染的闭环
android·人工智能·kotlin