如何修复在打瞌睡模式下错过警报的应用程序?

How to fix apps that miss alarms in doze mode?

某些应用程序,尤其是那些不再维护的应用程序,在装有 Marshmallow 的 android 设备进入休眠模式时会出现严重的错误行为。设计为闹钟替代品或计划程序以在未来执行某些任务的应用程序不再可靠地工作,完全违背了它们的目的。

解决方法为开发人员所熟知,或者受影响的应用程序是开源的,例如回答了 and documented here.

但作者不再维护的闭源应用程序如何修复?

请注意,如回答here

,禁用应用程序的电池优化对打瞌睡模式没有帮助

此答案适用于因使用 AlarmManagersetsetExact 方法而导致延迟唤醒的应用。这些方法设置的警报仅在打瞌睡 "maintenance" windows 或设备因用户干预或其他情况唤醒时发出。

解决方法是分别使用setAndAllowWhileIdlesetExactAndAllowWhileIdle方法;但能够修改和重新编译 apks 是诀窍。

  1. 获取 apktool:单击 "Current Release" link 下载 jar,apktool_2.1.1.jar 撰写本文时。
  2. 获取您要修复的应用程序的 apk。我用过apk20.com to find a downlaodable apk of the app I sought to fix, but there are also ways to get the apk of an app installed on the phone.
  3. 假设 java 二进制文件在您的路径中,并且 apktool jar 和 apk 在当前目录中,使用 apktool:

    反汇编 apk
    $ java -jar apktool_2.1.1.jar d com.example.android-app.apk
    

    反汇编文件(smali格式)将在当前目录com.example.android-app/下。

  4. 在所有反汇编的smali文件中用AlarmManager;->setExactAndAllowWhileIdle替换所有出现的AlarmManager;->set/setExact。您可以手动执行此操作,也可以使用 findsed:

    自动执行此操作
    $ find com.example.android-app -name *.smali -exec \
        sed -i -e 's/AlarmManager;->set\(Exact\)\?(/AlarmManager;->setExactAndAllowWhileIdle(/g' {} +
    

    这会将 setsetExact 替换为 setExactAndAllowWhileIdle

  5. 重建 apk:

    $ java -jar apktool_2.1.1.jar b com.example.android-app
    

    注意 b 表示构建,缺少 .apk 表示修改文件所在的目录。生成的 apk 创建为 com.example.android-app/dist/com.example.android-app.apk

  6. 签署 apk。如果您以前从未签署过 jar 文件,这将是烦人的部分:

    • 首先一步创建一个密钥库和一个签名密钥(official documentation):

      $ keytool -genkeypair -validity 36500
      Enter keystore password:  android
      Re-enter new password: android
      What is your first and last name?
        [Unknown]:
      What is the name of your organizational unit?
        [Unknown]:
      What is the name of your organization?
        [Unknown]:
      What is the name of your City or Locality?
        [Unknown]:
      What is the name of your State or Province?
        [Unknown]:
      What is the two-letter country code for this unit?
        [Unknown]:
      Is CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown correct?
        [no]:  yes
      
      Enter key password for <mykey>
              (RETURN if same as keystore password):
      

      这会在默认位置创建一个密码为 android 的密钥库和一个名为 mykey 的签名密钥,密码也为 android.

    • 现在签署重建的 apk (official documentation):

      $ jarsigner -tsa http://timestamp.digicert.com com.example.android-app/dist/com.example.android-app.apk mykey
      Enter Passphrase for keystore: android
      jar signed.
      

      这个签名过程是必不可少的,因为你的 android phone 将拒绝你的 apk,如果它没有用像这样的神秘消息签名:

      Parse error

      There was a problem parsing the package.

  7. 从您的 phone 中卸载原始应用程序。这是必不可少的,因为新的签名密钥与原作者的签名密钥不同,android 将在签名密钥更改时拒绝更新应用程序。如果您尝试更新 pak,内置包管理器将简单地告诉您:

    App not installed

    如有必要,您可能希望备份或保存应用程序的配置。

  8. Enable installation from unknown sources
  9. 将重建的 apk 获取到您的 phone 并安装它。有多种方法可以做到这一点,但这两种是最简单的:

    • enable USB debugging 然后 运行:

      $ adb install com.example.android-app/dist/com.example.android-app.apk
      
    • 通过 USB 将 apk 复制到 phone 的存储空间,在 phone 的浏览器中打开 file:///sdcard/ 并点击 apk 下载它,然后从下载器来安装它。

该应用程序现在应该可以在休眠模式下正常工作,而您的休眠模式在节省电池方面的效果可能会比以前略低,具体取决于固定应用程序引起的唤醒次数。