2026-01-12 13:30:25 +08:00
|
|
|
|
# 功耗优化工具链
|
2026-01-12 17:14:58 +08:00
|
|
|
|
|
|
|
|
|
|
## 概述
|
|
|
|
|
|
|
|
|
|
|
|
功耗优化是移动应用开发中的重要环节,直接影响用户体验和设备续航。本文档介绍Android功耗优化的工具链、分析方法和优化策略。
|
|
|
|
|
|
|
|
|
|
|
|
## 功耗分析工具
|
|
|
|
|
|
|
|
|
|
|
|
### 1. Battery Historian
|
|
|
|
|
|
|
|
|
|
|
|
Google官方提供的功耗分析工具,可以分析设备的电量消耗情况。
|
|
|
|
|
|
|
|
|
|
|
|
#### 安装与使用
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 安装Battery Historian
|
|
|
|
|
|
go get -u github.com/google/battery-historian
|
|
|
|
|
|
|
|
|
|
|
|
# 启动服务
|
|
|
|
|
|
cd $GOPATH/src/github.com/google/battery-historian
|
|
|
|
|
|
go run cmd/battery-historian/battery-historian.go
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 数据采集
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 重置电池统计
|
|
|
|
|
|
adb shell dumpsys batterystats --reset
|
|
|
|
|
|
|
|
|
|
|
|
# 执行测试场景
|
|
|
|
|
|
# ... 进行应用操作 ...
|
|
|
|
|
|
|
|
|
|
|
|
# 导出数据
|
|
|
|
|
|
adb bugreport > bugreport.txt
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 关键指标
|
|
|
|
|
|
|
|
|
|
|
|
- **Wake Lock**: 唤醒锁持有时间
|
|
|
|
|
|
- **CPU**: CPU使用率
|
|
|
|
|
|
- **Network**: 网络流量
|
|
|
|
|
|
- **GPS**: GPS使用情况
|
|
|
|
|
|
- **Screen**: 屏幕亮度与唤醒时间
|
|
|
|
|
|
|
|
|
|
|
|
### 2. Android Profiler
|
|
|
|
|
|
|
|
|
|
|
|
Android Studio内置的性能分析工具,可以实时监控功耗。
|
|
|
|
|
|
|
|
|
|
|
|
#### 使用步骤
|
|
|
|
|
|
|
|
|
|
|
|
1. 连接设备
|
|
|
|
|
|
2. 打开Android Profiler
|
|
|
|
|
|
3. 选择Energy标签
|
|
|
|
|
|
4. 监控电量消耗
|
|
|
|
|
|
|
|
|
|
|
|
#### 功能特点
|
|
|
|
|
|
|
|
|
|
|
|
- 实时监控
|
|
|
|
|
|
- 可视化展示
|
|
|
|
|
|
- 支持录制和回放
|
|
|
|
|
|
|
|
|
|
|
|
### 3. dumpsys batterystats
|
|
|
|
|
|
|
|
|
|
|
|
系统命令,可以获取详细的电池统计信息。
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 查看电池统计
|
|
|
|
|
|
adb shell dumpsys batterystats
|
|
|
|
|
|
|
|
|
|
|
|
# 查看特定应用的功耗
|
|
|
|
|
|
adb shell dumpsys batterystats com.example.app
|
|
|
|
|
|
|
|
|
|
|
|
# 重置统计
|
|
|
|
|
|
adb shell dumpsys batterystats --reset
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 4. Power Monitor
|
|
|
|
|
|
|
|
|
|
|
|
硬件级功耗监控工具,需要支持Power Monitor的设备。
|
|
|
|
|
|
|
|
|
|
|
|
## 功耗优化策略
|
|
|
|
|
|
|
|
|
|
|
|
### 1. CPU优化
|
|
|
|
|
|
|
|
|
|
|
|
#### 减少CPU唤醒
|
|
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
|
// 避免频繁唤醒CPU
|
|
|
|
|
|
// 使用JobScheduler替代AlarmManager
|
|
|
|
|
|
JobScheduler jobScheduler =
|
|
|
|
|
|
(JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
|
|
|
|
|
|
JobInfo jobInfo = new JobInfo.Builder(1, new ComponentName(this, MyJobService.class))
|
|
|
|
|
|
.setPeriodic(15 * 60 * 1000) // 15分钟
|
|
|
|
|
|
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
|
|
|
|
|
|
.build();
|
|
|
|
|
|
jobScheduler.schedule(jobInfo);
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 优化算法复杂度
|
|
|
|
|
|
|
|
|
|
|
|
- 使用高效的数据结构
|
|
|
|
|
|
- 避免不必要的循环
|
|
|
|
|
|
- 使用缓存减少计算
|
|
|
|
|
|
|
|
|
|
|
|
#### 后台任务优化
|
|
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
|
// 使用WorkManager管理后台任务
|
|
|
|
|
|
WorkRequest uploadWork = new OneTimeWorkRequest.Builder(UploadWorker.class)
|
|
|
|
|
|
.setConstraints(new Constraints.Builder()
|
|
|
|
|
|
.setRequiredNetworkType(NetworkType.CONNECTED)
|
|
|
|
|
|
.setRequiresCharging(true)
|
|
|
|
|
|
.build())
|
|
|
|
|
|
.build();
|
|
|
|
|
|
WorkManager.getInstance(context).enqueue(uploadWork);
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 网络优化
|
|
|
|
|
|
|
|
|
|
|
|
#### 批量请求
|
|
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
|
// 合并多个小请求为一个批量请求
|
|
|
|
|
|
// 减少网络唤醒次数
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 使用缓存
|
|
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
|
// 使用HTTP缓存减少网络请求
|
|
|
|
|
|
CacheControl cacheControl = new CacheControl.Builder()
|
|
|
|
|
|
.maxAge(1, TimeUnit.HOURS)
|
|
|
|
|
|
.build();
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 压缩数据
|
|
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
|
// 使用Gzip压缩
|
|
|
|
|
|
// 减少传输数据量
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 3. Wake Lock管理
|
|
|
|
|
|
|
|
|
|
|
|
#### 及时释放Wake Lock
|
|
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
|
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
|
|
|
|
|
|
WakeLock wakeLock = powerManager.newWakeLock(
|
|
|
|
|
|
PowerManager.PARTIAL_WAKE_LOCK, "MyApp::MyWakelockTag");
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
wakeLock.acquire();
|
|
|
|
|
|
// 执行需要保持唤醒的操作
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
if (wakeLock.isHeld()) {
|
|
|
|
|
|
wakeLock.release();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 使用超时机制
|
|
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
|
// 设置超时,避免长时间持有
|
|
|
|
|
|
wakeLock.acquire(10 * 60 * 1000L); // 10分钟超时
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 4. 定位服务优化
|
|
|
|
|
|
|
|
|
|
|
|
#### 使用低功耗定位
|
|
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
|
LocationRequest locationRequest = LocationRequest.create()
|
|
|
|
|
|
.setPriority(LocationRequest.PRIORITY_LOW_POWER)
|
|
|
|
|
|
.setInterval(60000) // 1分钟
|
|
|
|
|
|
.setMaxWaitTime(5 * 60 * 1000); // 5分钟最大等待
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 及时停止定位
|
|
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
|
// 不需要定位时立即停止
|
|
|
|
|
|
locationManager.removeUpdates(locationListener);
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 5. 屏幕优化
|
|
|
|
|
|
|
|
|
|
|
|
#### 降低屏幕亮度
|
|
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
|
// 根据环境光自动调整
|
|
|
|
|
|
WindowManager.LayoutParams params = getWindow().getAttributes();
|
|
|
|
|
|
params.screenBrightness = 0.5f; // 50%亮度
|
|
|
|
|
|
getWindow().setAttributes(params);
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 减少屏幕唤醒时间
|
|
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
|
// 设置屏幕超时时间
|
|
|
|
|
|
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
|
|
|
|
|
// 使用后及时清除
|
|
|
|
|
|
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 6. 后台任务优化
|
|
|
|
|
|
|
|
|
|
|
|
#### 使用Doze模式
|
|
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
|
// 适配Doze模式
|
|
|
|
|
|
// 使用白名单机制
|
|
|
|
|
|
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
|
|
|
|
|
|
boolean isIgnoringBatteryOptimizations =
|
|
|
|
|
|
powerManager.isIgnoringBatteryOptimizations(getPackageName());
|
|
|
|
|
|
|
|
|
|
|
|
if (!isIgnoringBatteryOptimizations) {
|
|
|
|
|
|
Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
|
|
|
|
|
|
intent.setData(Uri.parse("package:" + getPackageName()));
|
|
|
|
|
|
startActivity(intent);
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 延迟非紧急任务
|
|
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
|
// 使用JobScheduler延迟执行
|
|
|
|
|
|
JobInfo jobInfo = new JobInfo.Builder(1, componentName)
|
|
|
|
|
|
.setMinimumLatency(30 * 60 * 1000) // 延迟30分钟
|
|
|
|
|
|
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
|
|
|
|
|
|
.build();
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 功耗测试方法
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 基准测试
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 1. 重置电池统计
|
|
|
|
|
|
adb shell dumpsys batterystats --reset
|
|
|
|
|
|
|
|
|
|
|
|
# 2. 执行测试场景(30分钟)
|
|
|
|
|
|
# 模拟用户正常使用
|
|
|
|
|
|
|
|
|
|
|
|
# 3. 导出数据
|
|
|
|
|
|
adb bugreport > bugreport.txt
|
|
|
|
|
|
|
|
|
|
|
|
# 4. 分析Battery Historian报告
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 对比测试
|
|
|
|
|
|
|
|
|
|
|
|
- 优化前后对比
|
|
|
|
|
|
- 竞品对比
|
|
|
|
|
|
- 不同设备对比
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 场景测试
|
|
|
|
|
|
|
|
|
|
|
|
- 待机场景
|
|
|
|
|
|
- 使用场景
|
|
|
|
|
|
- 后台场景
|
|
|
|
|
|
|
|
|
|
|
|
## 常见问题
|
|
|
|
|
|
|
|
|
|
|
|
### 1. Wake Lock泄漏
|
|
|
|
|
|
|
|
|
|
|
|
**症状**: 设备无法进入休眠
|
|
|
|
|
|
|
|
|
|
|
|
**排查**:
|
|
|
|
|
|
```bash
|
|
|
|
|
|
adb shell dumpsys power
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**解决**: 检查所有Wake Lock的acquire/release配对
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 后台网络请求过多
|
|
|
|
|
|
|
|
|
|
|
|
**症状**: 待机时仍有网络流量
|
|
|
|
|
|
|
|
|
|
|
|
**排查**: Battery Historian查看Network统计
|
|
|
|
|
|
|
|
|
|
|
|
**解决**: 使用JobScheduler批量处理
|
|
|
|
|
|
|
|
|
|
|
|
### 3. GPS持续定位
|
|
|
|
|
|
|
|
|
|
|
|
**症状**: 定位服务一直运行
|
|
|
|
|
|
|
|
|
|
|
|
**排查**: Battery Historian查看GPS统计
|
|
|
|
|
|
|
|
|
|
|
|
**解决**: 及时停止定位服务
|
|
|
|
|
|
|
|
|
|
|
|
## 最佳实践
|
|
|
|
|
|
|
|
|
|
|
|
1. **最小化原则**: 只做必要的工作
|
|
|
|
|
|
2. **批量处理**: 合并多个小任务
|
|
|
|
|
|
3. **延迟执行**: 非紧急任务延迟处理
|
|
|
|
|
|
4. **及时释放**: 用完资源立即释放
|
|
|
|
|
|
5. **监控告警**: 建立功耗监控体系
|
|
|
|
|
|
|
|
|
|
|
|
## 相关链接
|
|
|
|
|
|
|
|
|
|
|
|
- [[README]]
|
|
|
|
|
|
- [[启动优化方法论]]
|
|
|
|
|
|
- [[09-调试与工具链/Systrace_Perfetto全解读]]
|