Partial Wake Locks

和你一起终身学习,这里是程序员Android

本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以下内容:

一、发现问题

Partial wake locks 是 PowerManager API 中的一种机制。可让开发人员在设备显示屏关闭(无论是由于系统超时还是用户按下电源按钮)之后,继续让CPU保持运行状态。

您的应用通过 acquire() 使用 PARTIAL_WAKE_LOCK 标志调用来获取部分唤醒锁。

如果部分唤醒锁 在您的应用程序在后台运行时被长时间Hold,则会 stuck(用户看不到应用程序的任何部分)。

这种情况会耗尽设备的电池电量,因为它会阻止设备进入低功耗模式。建议Partial wake locks应仅在必要时使用,并且不需要时立即释放。

如果您的应用有 Partial wake locks卡住,则可以使用下文中的指导来诊断和解决问题。

一、发现问题

您可能并不总是知道App被 Partial wake locks卡住了。如果您已经发布了应用程序,则Android vitals可帮助您了解问题。

Android vitals

当您的应用程序显示卡住的部分唤醒锁时 ,Android vitals可以通过Play Console提醒您,从而帮助提高应用程序的性能 。Android vitals主要报告 partial wake locks卡住至少一个小时以上的问题,比如:

  • 至少占整个电池消耗的0.70%

  • 仅在后台运行时,至少有0.10%的电池电量消耗

电池电量是指两次充满电的间隔,显示的电池续航次数是该应用程序所有测量用户的汇总。有关Google Play如何收集Android生命数据的信息,请参阅 Play Console文档。

一旦知道您的应用程序卡住了部分唤醒锁,下一步就是解决该问题。

二、解决问题

唤醒锁是在Android平台的早期版本中引入的,但是随着时间的推移,以前需要唤醒锁的许多用例现在可以通过诸如WorkManager更新的API更好地解决问题。

本节包含修复唤醒锁的技巧,但从长远来看,请考虑迁移您的应用程序,以遵循 第四部分最佳实践 中的建议。

在代码中标识并修复需要唤醒锁的位置,例如newWakeLock(int ,String)WakefulBroadcastReceiver(Android O 已弃用)

  • newWakeLock(int ,String)

 PowerManager pm = (PowerManager)mContext.getSystemService(
                                          Context.POWER_SERVICE);
 PowerManager.WakeLock wl = pm.newWakeLock(
                                      PowerManager.SCREEN_DIM_WAKE_LOCK
                                      | PowerManager.ON_AFTER_RELEASE,
                                      TAG);
 wl.acquire();
 // ... do work...
 wl.release();
 

1.建议在唤醒锁标记包名、类名、方法名

这样方便您可以轻松地在源码中标识创建唤醒锁的位置。以下是一些其他提示:

  • 忽略名称中的任何个人身份信息(PII),例如电子邮件地址。否则,设备将记录日志,_UNKNOWN 而不是唤醒锁名称。

  • 不要以编程方式获取类或方法的名称,例如通过调用 getName() ,因为Proguard可能会混淆它们。而是使用硬编码的字符串。

  • 不要添加计数器或唯一标识符来唤醒锁定标签。系统将无法聚合通过相同方法创建的唤醒锁,因为它们都具有唯一的标识符。

2.确保您的代码释放了它获取的所有唤醒锁

准确的使用 acquire()及release(),避免异常导致无法是否唤醒锁。

  • 举例由于未捕获的异常导致未释放的唤醒锁

    void doSomethingAndRelease() throws MyException {
        wakeLock.acquire();
        doSomethingThatThrows();
        wakeLock.release();  // does not run if an exception is thrown
    }

正确的写法应该如下

    void doSomethingAndRelease() throws MyException {
        try {
            wakeLock.acquire();
            doSomethingThatThrows();
        } finally {
            wakeLock.release();
        }
    }

3.确保唤醒锁在不再需要时被释放

如果您使用唤醒锁来允许后台任务完成,请确保该任务完成时及时释放唤醒锁。如果唤醒锁保持的时间比预期的要长而不被释放,则可能意味着您的后台任务花费的时间比预期的要多。

三、验证问题

解决了代码中的问题后,请使用以下Android工具验证您的应用正确释放了唤醒锁:

1.dumpsys

dumpsys提供设备上系统服务状态的信息。可以通过使用adb命令看电源服务的状态(包括唤醒锁列表)adb shell dumpsys power

C:\Users\Administrator>adb shell dumpsys power
POWER MANAGER (dumpsys power)

Power Manager State:
  ... ...
  mBatteryLevel=46   // 电量信息
  mBatteryLevelWhenDreamStarted=0
  mDockState=0
  mStayOn=false
  mProximityPositive=false //Psensor
  mBootCompleted=true
  mSystemReady=true
  ... ...

Settings and Configuration:
  
  ... ...
  mScreenBrightnessSettingMinimum=30  //屏幕连读参数
  mScreenBrightnessSettingMaximum=255
  mScreenBrightnessSettingDefault=102
  mScreenBrightnessForVrSettingDefault=86
  mScreenBrightnessForVrSetting=86
  mDoubleTapWakeEnabled=false
  mIsVrModeEnabled=false
  ... ...

Suspend Blockers: size=4  //唤醒中断源
  PowerManagerService.WakeLocks: ref count=0
  PowerManagerService.Display: ref count=0
  PowerManagerService.Broadcasts: ref count=0
  PowerManagerService.WirelessChargerDetector: ref count=0
  ... ...

2.Battery Historian

Battery Historian 一种将 Android Bugreport的输出解析为与电源相关的事件的可视表示的工具。bugreport,并通过BatteryHistorian分析唤醒源。

adb shell dumpsys batterystats --reset
adb shell dumpsys batterystats --enable full-wake-history
adb bugreport bugreport.zip

BatteryHistorian 详细使用方法,请点击下方链接。

四、最佳实践

通常,应用应避免部分唤醒锁定,因为这样很容易耗尽用户的电池。Android为需要部分唤醒锁的用例提供了替代API。部分唤醒锁的另一个用例是确保屏幕关闭时音乐应用程序继续播放。如果您使用唤醒锁来运行任务,请考虑在background processing guide.

  • 确保您的应用程序的某些部分保留在前台。例如,如果您需要运行服务,请start a foreground service。直观地向用户表明您的应用仍在运行。

  • 确保获取和释放唤醒锁的逻辑尽可能简单。当您的唤醒锁逻辑与混淆多种状态,超时,执行程序池和/或回调事件相关联时,该逻辑中的任何细微错误都可能导致唤醒锁的保存时间超出预期。这些错误很难诊断和调试。

友情推荐

Android开发干货分享

至此,本篇已结束,如有不对的地方,欢迎您的建议与指正。同时期待您的关注,感谢您的阅读,谢谢!

640?wx_fmt=png

posted @ 2019-09-26 08:08  程序员Android的博客  阅读(221)  评论(0编辑  收藏  举报