Kum*_* C. 5 android alarmmanager android-7.1-nougat
背景: 我有一个在 Android 7.1 上运行的 Android 应用程序。使用 AlarmManage 设置重复任务,以便每天在特定时间执行任务。代码如下:
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
long startInMs = getComing9AM();
Intent intent = ...; //an intent to be run when alarm time is up.
PendingIntent ScheduledIntent = PendingIntent.getBroadcast(context, id, intent, 0);
am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, startInMs, ScheduledIntent);
private long getComing9AM(){
long now = System.currentTimeMillis();
long today = getToday9AM();
return (now < today? today:getTomorrow9AM());
}
private long getToday9AM(){
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 9);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
return calendar.getTimeInMillis();
}
private long getTomorrow9AM(){
return getToday9AM() + 7 * 24 * 3600 * 1000;
}
Run Code Online (Sandbox Code Playgroud)
问题描述:
分析结果:
检查问题模式后,发现自上次启动后约 25 天,该任务将无法工作。作为对数字敏感的数学极客,“25 天”= 2,160,000 秒 = 2,160,000,000 毫秒。而这个值非常接近于 2^31-1 (Integer.MAX_VALUE),相当于 24.85 天。
HDMI 线已插入设备,屏幕显示无输入。
即使在 25 天后(通过 HTTPS)分配了新的计划任务,该任务也不会执行。
将 USB 设备(我尝试使用鼠标)插入设备后,Android 被唤醒(屏幕有显示)。并且Android已经唤醒,任务可以每天正常运行,直到接下来的25天。
使用ADB检查Android设置,我只能发现一个参数值是Integer.MAX_VALUE。即(adb shell dumpsys power):
mMaximumScreenOffTimeoutFromDeviceAdmin=2147483647 (enforced=false) 屏幕关闭超时:2147483647 ms
根据发现 #5,我尝试将屏幕关闭超时设置为 60000 以尝试重现该问题。但是任务仍然可以照常运行。
它不应该与打盹模式相关,因为设备总是在充电并且没有电池。
(新发现)dumpsys power 中“mWakefulness”的值是 24.85 天后的睡眠。在 24.85days 之前,这个值应该是Awake。
(新发现)鉴于 wWakefulness=Asleep arelay,“mLastSleepTime”=now - (startupTimestamp + 24.85day)。
寻求建议:
我想有一些方向来进一步调查这个问题。
我想知道是否有办法在应用程序中模拟唤醒事件?(作为找到根本原因之前的解决方法)。
我想得到一些指导来进一步调查这个问题。
我会找到对代码进行单元测试的方法,以确保其正常工作。您可以定期激发意图并尝试一下。在单元测试中或通过adb。您提到“通过 https”,但也许您需要直接进入“金属”并自己触发方法进行测试。
我想知道是否有办法在应用程序中模拟唤醒事件?(作为查找根本原因之前的解决方法)。
您的设备不是手机,所以我不确定它是否能够接收 Firebase 推送通知(或任何形式的通知),因为您需要 Google Play 服务来实现此目的,并且还附带了另一包东西,但我会尝试手动控制这些事件(外部)以确保您的代码不会导致问题。每天上午 9 点发出“嘟嘟声”(或打印到 logcat)是否仍然有效?
如果 AlarmManager 在 NN 天后以某种方式周期性地中断,那么有些东西要么真的坏了(说实话,这很奇怪,7.1 相当旧并且已经使用了很长时间,有人会对此说些什么,我希望(? )),或者你的代码行为不当。
开始隔离事物,您可以创建一个简单的应用程序,它所做的只是每天上午 9:30 打印日志。还有效吗?
或者工作经理会在这里帮助您还是会有其他您无法使用/拥有的依赖项?当然,这需要权衡,因为 WorkManager 与 AlarmManager 不同,并且受到更多限制。
即使在 25 天后分配新的计划任务(通过 HTTPS),该任务也不会执行。
这也令人费解,因为 AlarmManager 似乎完全停止工作和接收工作。adb如果您此时手动广播意图,这项工作是否有效?您有不止一台这样的设备吗?所有人都会遇到这种情况吗?
这是一个非常有趣的问题,我希望我有更具体的东西,但很少有人会知道与谷歌试图在手机上“节省电池”的所有新方法相关的内部工作原理。AlarmManager
setExactAndAllowWhenIdle描述为:
与其他警报不同,系统可以自由地重新安排此类警报,使其与任何其他警报(甚至来自同一应用程序的警报)不按顺序发生。当设备空闲时,这种情况显然会发生(因为该警报可以在空闲时关闭,此时应用程序中的任何其他警报将保留到稍后),但即使在不空闲时也可能发生。请注意,与常规的精确警报相比,操作系统将允许自己更灵活地安排这些警报,因为应用程序已选择此行为。当设备空闲时,它可能会采取更多的调度自由来优化电池寿命。
操作系统是否可以允许自己以某种形式灵活并忽略您的警报?嗯不确定。
最后的评论,您看过AlarmManager 的源代码吗?也许这里面有暗示。
最后,这篇长文(应该是评论)并没有真正给你一个解决方案,只是一个让我倾诉想法的开放场所。:) 如果需要的话我会更新;请告诉我们您发现了什么:)
作为旁注:我会测试您是否可以使用 Gradle 4.x 并有权访问 Java 8 API java.time(比日历甚至 util.Date 好得多),或者尝试利用(现已存档/弃用,但仍然可以使用一段时间,直到 Gradle 4.x 被“简化”)来自 Wharthon 的 ThreeTenABP 抽象使用相同的 Java8 API(从 ThreeTen 迁移到java.time实际上是一个 10 分钟的查找/替换来更改导入)。
简而言之,您可以将所有日历废话替换为
val tomorrowAt9Am = ZonedDateTime.now().plusDays(1).withHour(9).withMinute(0).withSecond(0).toEpochSecond()
编辑:你发现的最后两点(mWakeiness)非常有趣,我会继续寻找。与此同时,我在 Android 代码库中发现了该变量的一些实例。最有趣的是来自 AttentionDetector 的这个(多名字啊);随意浏览所有结果
| 归档时间: |
|
| 查看次数: |
101 次 |
| 最近记录: |