15. 如何请求忽略电池优化:REQUEST_IGNORE_BATTERY_OPTIMIZATIONS权限

嗯,这一节我们来聊聊一个让很多开发者又爱又恨的权限——REQUEST_IGNORE_BATTERY_OPTIMIZATIONS。说白了,它就是让App能绕过Doze模式限制的“通行证”。

我在项目中遇到过不少次,产品经理跑过来说:“我们的IM应用怎么收不到推送了?” 我一查,好家伙,被Doze模式给“掐断”了。这时候,这个权限就成了一个可能的解决方案。

15.1 这个权限到底是什么?

先别急着写代码。我们得搞清楚,这个权限的本质是什么。

Android从6.0(API 23)开始引入了Doze模式。系统会限制后台网络、延迟Alarm、禁止WakeLock。而REQUEST_IGNORE_BATTERY_OPTIMIZATIONS权限,就是让App告诉系统:“嘿,别优化我,我有特殊需求。”

核心要点:这个权限不是让你“禁用”Doze,而是让你的App被列入“白名单”。系统仍然会进入Doze,但你的App可以正常使用网络、Alarm和WakeLock。

15.2 权限声明与请求流程

好,我们来看看具体怎么操作。分两步走:声明权限 + 发起请求。

15.2.1 在Manifest中声明

<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />

这一步很简单,但要注意:这只是声明你有资格去请求,不代表系统会自动给你授权。

15.2.2 检查并请求权限

我个人习惯在App启动时或者关键功能入口处检查。比如,一个导航App,用户开始导航时,就应该请求这个权限。

// 检查是否已被忽略电池优化
String packageName = getPackageName();
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
if (pm != null && !pm.isIgnoringBatteryOptimizations(packageName)) {
    // 需要请求权限
    Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
    intent.setData(Uri.parse("package:" + packageName));
    startActivityForResult(intent, REQUEST_CODE_IGNORE_BATTERY_OPTIMIZATIONS);
}

小提示:请求时一定要带上intent.setData(Uri.parse("package:" + packageName))。如果不带,系统会弹出一个列表让用户自己选App,体验很差。我刚开始就踩过这个坑。

15.3 什么时候该用?什么时候不该用?

你想想看,Google设计Doze模式就是为了省电。如果每个App都请求忽略优化,那Doze就形同虚设了。所以,Google Play对使用这个权限有严格限制。

场景 是否推荐使用 说明
即时通讯/推送 谨慎使用 建议优先使用FCM(Firebase Cloud Messaging)高优先级推送
导航/地图 推荐使用 导航过程中需要持续定位和网络,Doze会严重影响体验
音乐/播客播放 不推荐 使用前台服务即可,不需要这个权限
运动/健康追踪 视情况而定 如果是后台持续记录,可以考虑;如果是前台运动,用前台服务即可
普通工具类App 绝对不要用 滥用会导致应用被下架

警告:Google Play审核非常严格。如果你的App不属于“核心功能需要持续后台运行”的类型,提交审核时大概率会被拒。我曾经有一个项目,因为用了这个权限做后台数据同步,被Google Play打回来三次,最后不得不改用WorkManager。

15.4 核心逻辑流程图

下面这张图,我画的是整个请求流程的核心逻辑。你看一遍就能明白,从检查到请求,再到用户选择,每一步都环环相扣。

REQUEST_IGNORE_BATTERY_OPTIMIZATIONS 请求流程 开始请求 检查 isIgnoringBatteryOptimizations() 是否已被列入白名单? 是否已忽略? 无需操作 发起 Intent 请求 ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS 用户选择:允许 / 拒绝

15.5 用户拒绝后怎么办?

这是很多开发者忽略的地方。用户点了“拒绝”,然后呢?

我曾经见过一些App,用户拒绝后就不停地弹窗请求,结果被用户直接卸载。这种做法非常不推荐。

我的建议是:

  • 不要反复弹窗。用户拒绝后,至少等一周再考虑再次请求。
  • 提供降级方案。比如,如果用户拒绝忽略电池优化,你可以引导用户使用前台服务,或者使用WorkManager的约束条件来保证任务执行。
  • 做好用户教育。在请求前,先弹一个说明对话框,告诉用户为什么需要这个权限,以及不授权会有什么影响。

重要提醒:从Android 11开始,系统对ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS的响应做了调整。即使用户在系统设置中手动将App加入白名单,你的App也无法通过isIgnoringBatteryOptimizations()检测到。嗯,这一点坑了不少人,我在做Android 11适配时就发现了这个变化。

15.6 替代方案:不用权限也能干活

说实话,我个人不太建议轻易使用这个权限。能用替代方案,就尽量用替代方案。

需求场景 替代方案 优点
定时任务 WorkManager + 约束条件 系统自动管理,省电且可靠
推送消息 FCM高优先级推送 即使Doze也能唤醒设备短暂处理
后台定位 前台服务 + 通知 用户可见,系统不会限制
后台播放 前台服务 + 媒体会话 标准做法,兼容性好
短时后台任务 JobScheduler 系统会合并任务,减少唤醒次数

我的经验:在大多数情况下,前台服务 + 合适的通知,就能解决90%的“后台被限制”问题。只有像导航、VoIP通话这类真正需要持续后台运行的应用,才值得去请求这个权限。

15.7 总结一下

这个权限,说白了就是一把双刃剑。用好了,能保证核心功能正常运行;用不好,既费电又可能被应用商店下架。

我的建议是:先想清楚你的App是不是真的需要。如果确实需要,那就按照规范流程来请求,并且做好用户拒绝后的降级方案。如果不需要,千万别滥用。

嗯,关于这个权限的内容就讲到这里。记住,尊重用户的电池,就是尊重用户的选择。


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