副标题:流氓应用Android6.0生存指南

我跟你们说,周三给五儿子升级了android6.0,周四起床失败,周五上课在下课前赶到,简直整个人都和吃了苍蝇一样。

而一切的根源都是因为我用了第三方闹钟应用而Android又踏马改休眠机制啦!

于是google搜了一下,我一看,哇!

Starting from Android 6.0 (API level 23), Android introduces two power-saving features that extend battery life for users by managing how apps behave when a device is not connected to a power source. Dozereduces battery consumption by deferring background CPU and network activity for apps when the device is unused for long periods of time. App Standby defers background network activity for apps with which the user has not recently interacted.

Doze is particularly likely to affect activities thatAlarmManager alarms and timers manage, because alarms in Android 5.1 (API level 22) or lower do not fire when the system is in Doze.

To help with scheduling alarms, Android 6.0 (API level 23) introduces two new AlarmManager methods:setAndAllowWhileIdle() and setExactAndAllowWhileIdle(). With these methods, you can set alarms that will fire even if the device is in Doze.

引用来源:Optimizing for Doze and App Standby | Android Developers

而我们都知道,闹钟都是用AlarmManager.setExact来实现核心功能的,而从AlarmManager | Android Developers可以知道,setExact和setExactAndAllowWhileIdle的参数列表是一致的,这样就以为着我们可以反编译直接修改API来实现适配Android6.0。

我用的第三方闹钟应用叫myClock 2,这个应用已经一万年没有更新惹。

通过grep . -re AlamManager|grep Exact查找AlarmManager调用(注意setExact是在4.4 Kitkat中引入的新API,如果闹钟应用更古老,可能使用的直接是set),然后将它改成setExactAndAllowWhileIdle。

注意还有一个暗坑:

Note: Neither setAndAllowWhileIdle() nor setExactAndAllowWhileIdle() can fire alarms more than once per 15 minutes per app.

Google还提供了测试是否起效的方法

  1. 插入USB调试
  2. 关闭屏幕
  3. 重复第二步数次直到屏幕显示Stepped to: IDLE
  4. 现在进入Doze模式

 

引申:

可以使用Xposed将应用的setExactAndAllowWhileIdle改成setExact,setAndAllowWhileIdle改成set,这样开启屏幕立马能得到推送之类的消息,休眠之后就不会再被唤醒。不知道绿色守护会不会这么搞。