【问题标题】:Understanding & testing Android M+ Doze Mode了解和测试 Android M+ 打盹模式
【发布时间】:2018-02-24 10:27:24
【问题描述】:

我正在努力让我的 Android 应用成为后 Android M 世界的好公民,这对应用在设备打瞌睡时可以/不能做什么施加了严格的限制。我对所涉及的问题的理解还比较零散,所以我希望这里有人可以填补空白。

打瞌睡的持续时间

我自己的经验发现

  • 在静止、屏幕关闭、不活动大约半小时内开始打瞌睡
  • 第一个维护窗口发生在 30 分钟内
  • 下一个发生在大约一个小时后
  • 在 ca 2、4 和 6 小时之后的那些。除此之外,我还没有测试过

这些是官方的 Android 打瞌睡期还是只是一种经验观察。

以上所有内容均在 Android N 设备上。

在打盹模式下测试应用

  • 使用 ADB 将设备连接到计算机
  • 将应用程序置于前台
  • 关闭设备屏幕
  • 来自命令行问题adb shell dumpsys battery unplug
  • 现在循环执行命令 `adb shell dumpsys deviceidle step light OR deep
  • 终于发出adb shell dumpsys battery reset

进入/退出打瞌睡

  • 在屏幕关闭且设备未受到移动时发生

  • 大概这使用了手机中的运动传感器,所以安静地坐在非常平稳移动的火车上的手机仍然会打瞌睡?

  • 如果我拿起一部打瞌睡的手机并开始带着它四处走动而没有与之交互,它会自动退出打盹吗?

  • 假设我的应用程序在其主机设备进入休眠状态时不在前台。然后我再次开始使用该设备,但没有访问该应用程序。它会自动重新开始“工作”吗,即

  • 它的广播接收器会起作用吗?

  • 它的处理程序将开始工作?

  • setRequiresDeviceIdle(true) 的计划作业将停止被调用吗?

打盹和作业调度的各种模式

  • 据我了解,有两种打瞌睡模式 LIGHT 和 DEEP。它们都有子模式

  • LIGHT:活动、空闲、空闲_维护、覆盖。我不明白各种模式的作用。我从 ADB 发出了step light,屏幕打开并看到了返回值ACTIVE。关闭屏幕step light 返回IDLE。

  • DEEP:Active,IDLE_PENDING,SENSING,LOCATING,IDLE,IDLE_MAINTENANCE 屏幕打开也返回ACTIVE,但屏幕关闭时返回IDLE_PENDING。那么其他子模式,IDLE,SENSING...什么时候发生呢?

我假设IDLE_MAINTENANCE 发生在设备从 DOZE 进入维护窗口并尝试运行来自各种应用的待处理作业请求时。

但如果是这种情况,为什么当我在应用程序中的计划作业运行时检查PowerManager.isDeviceIdleMode() 和PowerManger.isPowerSaveMode()总是返回false?

JobInfo.Builder 非常友好地允许您设置诸如setMinimumLatency 和setOverrideDeadline 之类的标准,但据我所知,OS hen 去并愉快地忽略它们 - 有时我的工作在几秒钟内运行其他时间相隔两个小时。

为什么没有 API 函数来测试 Doze 及其子模式?我希望在PowerManager 中找到它,但我发现只有isDeviceIdleMode 和isPowerSaveMode 在测试时始终返回false

打盹模式下的应用

  • 会所有其后台服务被破坏吗?

  • 不会得到正常的优先级推送消息?

  • 不会响应警报 - 但除了 setAndAllowWhenIdle 之外是吗?

  • 不会从它的任何广播接收器中获得任何通信?

  • 将无法通过套接字连接到外部世界 - 所以推送消息、发布/订阅等将不起作用?

  • 将立即销毁 Android 清单中声明的​​所有广播接收器。这是我自己的发现 - 我从 Java 代码创建的接收器保持不变,尽管它们在打瞌睡时不起作用。

我自己的应用通过设置广播接收器并调用.FusedLocationApi.requestLocationUpdates 来监视地理位置变化。此接收器在打盹/唤醒周期中存活。但是,是否可以保证我的LocationUpdates 请求在醒来后仍然会得到兑现?

我遇到了一个相当奇怪的错误。我发现我在打瞌睡中安排的工作在某些情况下运行得太近了,即使我给它们提供了 900,000 毫秒(15 分钟)的延迟和 1,000,000 毫秒的截止日期。我想我可以通过跟踪我这样做的最后一次运行时间来测试最后一次运行作业的时间来解决这个问题

private static Boolean shortInstantGap()
{
  Long instantNow = Instant.now().getEpochSecond();
  if (300 > (instantNow - this.lastInstant)) return true;
  //ignore the job opportunity if the last one was
  //less than 300s (5 minutes) ago
  this.lastInstant = instantNow;
  return false;
 }

然后中止作业槽

private static Runnable timeRunner = new Runnable() 
{
 @Override
 public void run() 
 {
  if (shortInstantGap()) return;
  callMyHandlerCode();
 }
};

但是,我发现当我通过屏幕关闭屏幕打开周期时,如果它在屏幕上,此代码会导致操作系统突然终止我的应用程序。为什么会这样?

最后,是不是没有一个 API 调用我可以用来测试设备刚刚从打瞌睡状态恢复,以便我有机会做一些打瞌睡后的内务处理?

【问题讨论】:

  • 你在这里问了很多问题。我会修剪它。您可以轻松地将其分成两个独立但相互关联的问题。我想回答,但要解决的问题太多了。
  • 很多重要的问题,太糟糕了,所以像往常一样不屑一顾:) 你找到答案了吗?我真的可以利用这些知识。
  • 很遗憾,不是。我已经为自己找到了一些答案,但绝不是全部。我可能会在某个时候用我自己的答案更新这个帖子。
  • 请问有人找到解决方案了吗?

标签: android-6.0-marshmallow android-doze


【解决方案1】:

好帖子和问题。貌似网上没有关于打盹模式的详细分析和资料。一些关键问题,如延迟通知、浏览器选项卡和 ui 不断重新加载等,一定是由于 Android 操作系统的打瞌睡和自动杀戮/内存处理。这两件事有时可能联系在一起,因此它们结合在一起。很明显,作为操作系统的 Android 还不稳定(不幸的是多年后),有很多小/大问题,但最糟糕的是,谷歌及其开发团队似乎没有做太多事情。也许主要问题是Android/Java本身,也许Java不是一个稳定的好操作系统的好选择。或者问题可能是谷歌没有很多优秀的开发人员来处理问题和人们的请求。也许我认为最有可能两者结合。

无论如何,这里有一些小技巧,供那些想要分析打瞌睡的人以及那些已经不知道这些的人使用;

*无线调试功能可用于连接设备与电脑/adb工具。因此,在连接和进行测试时不需要 USB 电缆和为手机充电。我认为由于 Android 10 大多数设备在开发人员选项下都有无线调试选项,因此无需 USB 电缆设置即可本机工作。如果没有可用的 wifi 调试,则可以使用 USB 电缆进行设置。

*"adb shell dumpsys deviceidle" 此命令汇总了一些信息,例如打盹状态和子状态,可用于在打盹/应用程序测试期间检查当前状态。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-08-20
    • 1970-01-01
    • 2016-06-27
    • 1970-01-01
    • 2015-10-10
    • 1970-01-01
    • 2023-03-28
    • 2015-11-24
    相关资源
    最近更新 更多