我正在努力使我的 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
非常友好地允许您设置标准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 调用我可以用来测试设备刚刚从打瞌睡中返回,所以我有机会做一些打瞌睡后的家务?