24、电量管理:Doze模式适配、后台播放限制、省电策略

做车载多媒体开发,电量管理是个绕不开的坎儿。

你想想看,车机不像手机,手机没电了可以随时充。车机要是耗电太快,用户可能连导航都撑不到目的地。更别说,现在很多新能源车的中控屏一开就是半天,后台还在播音乐、跑地图。嗯,这里面的门道,我今天跟你好好聊聊。

24.1 Doze模式适配:别让你的App在后台“睡着”

Android从6.0开始引入了Doze模式。说白了,就是系统检测到设备长时间未使用,会进入深度休眠。这时候,你的App如果还在后台偷偷跑,系统会直接“断网+冻结”。

我在项目中遇到过一个问题:用户把车停在停车场,音乐App还在后台播放。结果Doze模式一触发,网络断了,下一首歌死活加载不出来。用户回来一上车,发现播放器卡住了。

核心要点: Doze模式下,网络访问会被挂起,JobScheduler和AlarmManager的触发频率会被大幅降低。

24.1.1 如何适配Doze模式?

我个人习惯的做法是:

  • 使用高优先级FCM消息:如果必须唤醒设备,用FCM的“高优先级”消息。但注意,别滥用。
  • 申请临时白名单:通过PowerManager.requestPowerWhitelist()让用户手动将你的App加入白名单。
  • 使用JobScheduler替代AlarmManager:JobScheduler在Doze模式下有更好的兼容性。
// 申请临时白名单示例
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
if (pm != null && !pm.isIgnoringBatteryOptimizations(getPackageName())) {
    Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
    intent.setData(Uri.parse("package:" + getPackageName()));
    startActivity(intent);
}
注意: 不要滥用白名单申请。Google Play有审核机制,滥用会被下架。车载场景下,建议只在播放音乐或导航时申请。

24.2 后台播放限制:Android 12以后的新规

Android 12开始,系统对后台播放做了更严格的限制。以前你可以在后台随便播音乐,现在不行了。系统会检测到你的App在后台长时间播放,然后直接杀掉进程。

为什么会这样?因为有些流氓App在后台偷偷播无声音频,保持进程存活。Google看不下去了,直接一刀切。

24.2.1 如何绕过限制?

其实不是绕过,而是合规使用。我建议的做法是:

  • 使用前台服务:播放音乐时,必须启动前台服务,并显示通知。这是最标准的做法。
  • 通知必须包含“停止”按钮:用户可以通过通知直接停止播放。
  • 不要长时间占用音频焦点:当其他App请求音频焦点时,你的App应该暂停或降低音量。
// 启动前台服务播放音乐
Intent serviceIntent = new Intent(this, MusicPlaybackService.class);
startForegroundService(serviceIntent);

// 在Service中创建通知
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
        .setContentTitle("正在播放")
        .setContentText("歌曲名称")
        .setSmallIcon(R.drawable.ic_music)
        .addAction(R.drawable.ic_stop, "停止", stopPendingIntent)
        .build();
startForeground(NOTIFICATION_ID, notification);
避坑指南: 我曾经在Android 13上踩过一个坑——前台服务通知必须立即显示,否则系统会直接抛异常。所以记得在onStartCommand()里第一时间调用startForeground()

24.3 省电策略:从代码层面优化

省电不是让用户去设置里关功能,而是开发者从代码层面做优化。我总结了几个实战经验:

24.3.1 减少网络请求

网络请求是耗电大户。每次请求都要唤醒射频模块,功耗很高。我的做法是:

  • 批量请求:把多个小请求合并成一个。
  • 使用缓存:图片、歌曲列表等静态数据,优先从缓存读取。
  • 降低刷新频率:比如歌词同步,不需要每秒都请求,可以每5秒同步一次。

24.3.2 优化定位服务

车载场景下,定位是必须的。但你可以:

  • 使用被动定位:当其他App已经获取了位置,你的App直接读取缓存。
  • 降低定位精度:导航时用高精度,后台时用低精度。
  • 合理设置更新间隔:不要设置成0,至少1000ms以上。
// 合理设置定位请求
LocationRequest request = new LocationRequest.Builder(Priority.PRIORITY_BALANCED_POWER_ACCURACY, 5000)
        .setMinUpdateIntervalMillis(2000)
        .build();

24.3.3 屏幕与音频优化

屏幕和音频是车机上最耗电的两个硬件。我的建议:

  • 降低屏幕亮度:在后台播放时,可以适当降低亮度。
  • 使用低功耗音频解码:比如AAC比MP3更省电。
  • 关闭不必要的传感器:比如陀螺仪、加速度计,不用时就注销监听。

24.4 知识体系总览

下面这张图,是我自己整理的电量管理知识体系。你可以对照着看,查漏补缺。

电量管理 Doze模式适配 FCM高优先级消息 临时白名单申请 JobScheduler替代AlarmManager 后台播放限制 前台服务+通知 通知含停止按钮 音频焦点管理 省电策略 减少网络请求+缓存 优化定位精度与频率 屏幕亮度与音频解码 核心目标:保证功能完整性的同时,最大限度降低功耗 适配Android 12+新规,避免后台被杀

24.5 实战中的避坑指南

最后,分享几个我踩过的坑:

  • 不要依赖WAKE_LOCK:以前我习惯用WakeLock保持CPU唤醒,但Android 12以后,系统会强制释放。现在改用前台服务才是正道。
  • 注意测试环境:Doze模式在模拟器上很难复现。我建议用真机,通过adb shell dumpsys deviceidle force-idle强制进入Doze模式测试。
  • 用户感知很重要:省电策略不能影响用户体验。比如降低定位精度,导航时千万别降,否则用户会骂娘。
我的习惯: 每次发布新版本前,我都会在车上实际跑一遍,开着导航、播着音乐,然后锁车走人。半小时后回来看看App还在不在运行。这个土办法,比任何测试工具都管用。

电量管理这块,说白了就是平衡。你要在功能完整性和省电之间找到那个平衡点。别为了省电阉割功能,也别为了功能把电耗光。嗯,多测试、多优化,慢慢就有感觉了。


公众号:蓝海资料掘金营,微信deep3321