(译)Partial Wake Locks卡住问题

作者: 程序员Android1 | 来源:发表于2019-09-25 14:22 被阅读0次

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

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

一、发现问题
二、解决问题
三、验证问题
四、最佳实践

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

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

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

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

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

一、发现问题

您可能并不总是知道AppPartial 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 详细使用方法,请点击下方链接。
BatteryHistorian使用详解

四、最佳实践

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

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

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

友情推荐:
Android 干货分享

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

相关文章

  • (译)Partial Wake Locks卡住问题

    和你一起终身学习,这里是程序员 Android 本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇...

  • 《Alan Wake》就要下架了

    《Alan Wake》是由芬兰的游戏公司,Remedy (台译:綠美迪) 制作的游戏。因为配乐版权到期的问题,可能...

  • Mac安装mpv视频播放器

    安装 如遇到卡住问题参考 【homebrew卡住问题解决】

  • Flutter 环境搭建问题记录

    问题:运行 flutter doctor 命令卡住问题解决解决:设置国内镜像 问题:Flutter 编译卡住 ...

  • xib 卡住问题

    记录上周项目中的一个问题。 在做项目中,突然xcode 异常退出,当时正在操作的页面是一个xib。然后再次打开项目...

  • Redis分布式锁

    Distributed locks with Redis Redis分布式锁 Distributed locks ...

  • influxdb写入数据遇到的错误

    partial write: max-values-per-tag limit exceeded 这个问题可能会出...

  • MySQL 锁(InnoDB Locking)

    一、属性锁:Shared and Exclusive Locks 1.1 简介 shared locks 是共享锁...

  • Locks

    与锁有关的操作 Acquire() :在进入临界区前调用 Release():在离开临界区后调用有的操作系统可能会...

  • Locks

    Atomic 原子操作是一种简单的同步形式,适用于简单的数据类型。原子操作的优点是它们不会阻塞竞争线程。对于简单的...

网友评论

    本文标题:(译)Partial Wake Locks卡住问题

    本文链接:https://www.haomeiwen.com/subject/nltmuctx.html