alarmmanager 的 setExactAndAllowWhileIdle() 无法正常工作

setExactAndAllowWhileIdle() for alarmmanager is not working properly

我正在开发一个应用程序,它需要在用户设置的确切时间执行特定操作。为此,我正在使用 setExactAndAllowWhileIdle() 方法,因为 this documentation 表示 android 具有 android 6.0 或更高版本的设备具有打瞌睡模式概念,如果设备保持空闲一段时间,它将进入打瞌睡模式,打瞌睡模式限制警报。如果我想在设备进入打瞌睡模式时触发我的警报,那么我有 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);

是方法问题还是我做的方法不对??

您可以通过忽略电池优化将您的应用从休眠模式列入白名单..

添加权限

<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 分钟发出一次以上的警报。

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

使用setAlarmClock()方法解决了我的问题。如果您使用 setAlarmClock() 方法设置闹钟,那么这将不允许系统在您的闹钟时间 1 小时之前进入打瞌睡模式。我通过在设置闹钟后手动强制我的设备进入打瞌睡模式来对此进行了测试。让我解释一下完整的场景。

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

adb shell dumpsys deviceidle force-idle

显示

unable to enter into doze mode

  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);

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

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