22

我正在努力使我的 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。他们都有子模式

  • 灯光:活动、空闲、空闲维护、覆盖。我不明白各种模式的作用。从 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非常友好地允许您设置标准setMinimumLatencysetOverrideDeadline但据我所知,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 调用我可以用来测试设备刚刚从打瞌睡中返回,所以我有机会做一些打瞌睡后的家务?

4

1 回答 1

-1

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

无论如何,这里有一些小技巧,供那些想要分析打瞌睡的人以及那些还没有意识到这些的人;

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

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

于 2022-02-01T11:40:53.960 回答