alarmmanager的setExactAndAllowWhileIdle()无法正常工作

我正在开发一个应用程序,需要对用户设置的确切时间执行特定操作。 为此,我使用setExactAndAllowWhileIdle()方法,因为该文档说具有android 6.0或更高版本的android设备具有打盹模式概念,其中如果设备保持空闲一段时间,则它将进入打盹模式并且打盹模式限制警报。 如果我想在设备处于打盹模式时触发警报,那么我有setExactAndAllowWhileIdle()方法,如文档所述。 本文档还包含将设备输入打盹模式以进行测试的手动方式。 所以,我正在测试使用这种方式但是当设备进入打盹模式时我的警报没有被触发,当我通过终端命令停止打盹模式时,我的过去警报将立即触发。

所以,我的问题是setExactAndAllowWhileIdle()这个方法在打盹模式下不起作用,但它必须像文档中所说的那样工作。 我知道这种方法的局限性,我每9分钟只能发出一次警报,而且我遵守这条规则。 所以,我无法理解问题出在哪里。

我的代码:

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC, d.getTime(), pendingIntent); else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) alarmManager.setExact(AlarmManager.RTC, d.getTime(), pendingIntent); else alarmManager.set(AlarmManager.RTC, d.getTime(), pendingIntent); 

这是一个方法问题还是我以错误的方式做到了?

我已经为我的问题找到了解决方案,我在这里发布了自己的答案,这对我有用。

使用setAlarmClock()方法解决了我的问题。 如果使用setAlarmClock()方法设置警报,则不允许系统在警报时间的1小时之前进入hibernate模式。 我通过手动强制我的设备在设置闹钟后进入打盹模式进行了测试。 让我解释完整的情景。

  1. 首先,我在当前时间5分钟后设置闹钟,然后尝试使用以下命令手动将设备置于打盹模式。

adb shell dumpsys deviceidle force-idle

表明

无法进入打盹模式

  1. 之后我从当前时间1小时1分钟后设置闹钟,然后我试图让我的设备进入打盹模式,并成功进入打盹模式。 然后我在我的设备上什么也没做,即使它处于打盹模式,也会准时准时发出警报。

因此,我得出结论,如果当前时间和闹钟时间之间存在少量时间戳,则setAlarmClock()方法会阻止您的设备进入打盹模式。 否则,如果您的设备已经处于打盹模式,那么它将在您的警报一段时间之前退出打盹模式,因此您的警报工作正常。

更新的代码:

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) alarmManager.setAlarmClock(new AlarmManager.AlarmClockInfo(d.getTime(),pendingIntent),pendingIntent); else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) alarmManager.setExact(AlarmManager.RTC, d.getTime(), pendingIntent); else alarmManager.set(AlarmManager.RTC, d.getTime(), pendingIntent); 

根据文件

RTC – 在指定时间触发挂起的意图但不唤醒设备。

RTC_WAKEUP – 唤醒设备以在指定时间触发挂起的意图。

使用AlarmManager.RTC_WAKEUP而不是AlarmManager.RTC

您可以通过忽略电池优化来将您的应用程序从打盹模式列入白名单。

添加权限

  

请求将您的应用列入白名单

 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { Intent intent = new Intent(); String packageName = getPackageName(); PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE); if (!pm.isIgnoringBatteryOptimizations(packageName)) { intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); intent.setData(Uri.parse("package:" + packageName)); startActivity(intent); } } 

注意:setAndAllowWhileIdle()和setExactAndAllowWhileIdle()都不能每个应用每15分钟触发一次警报。