alarmmanager的setExactAndAllowWhileIdle()无法正常工作

时间:2018-03-26 03:55:27

标签: java android alarmmanager

我正在开发一个应用程序,需要对用户设置的确切时间执行特定操作。为此我使用setExactAndAllowWhileIdle()方法,因为this documentation表示具有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);

这是方法问题还是以错误的方式进行?

4 个答案:

答案 0 :(得分:5)

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

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

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

    adb shell dumpsys deviceidle force-idle

    显示

      

    无法进入打盹模式

    1. 之后我在当前时间1小时1分钟后设置闹钟,然后我尝试将设备置于打盹模式,并成功进入打盹模式。然后我在我的设备上什么也没做,即使它处于打盹模式,它也准时准时发出警报。
    2. 因此,我得出结论,如果当前时间和闹钟时间之间存在少量时间戳,则setAlarmClock()方法会阻止您的设备进入打盹模式。否则,如果您的设备已经处于打盹模式,那么它会在您的警报响起之前退出打盹模式,因此,您的警报可以正常工作。

      更新代码:

      if self.cidades.contains(where: { $0.id == cidade.id}) {
           // found
      } else {
           // not
      }
      

答案 1 :(得分:1)

根据文件

  

RTC - 在指定时间触发待处理的意图,但不会唤醒   设备。

     

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

使用AlarmManager.RTC_WAKEUP代替AlarmManager.RTC

答案 2 :(得分:1)

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

添加权限

<uses-permission 
android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>

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

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分钟触发一次警报。

答案 3 :(得分:0)

@MarGin的答案中的一些补充。
用户在一个对话框中完成所有操作要容易得多,但这违反了Google Play政策

if (!powerManager.isIgnoringBatteryOptimizations(packageName)) {
    startActivity(
        Intent(
            Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS,
            Uri.parse("package:$packageName")
        )
    )
}