【问题标题】:setExactAndAllowWhileIdle() for alarmmanager is not working properly警报管理器的 setExactAndAllowWhileIdle() 无法正常工作
【发布时间】:2020-02-27 21:19:11
【问题描述】:

我正在开发一个应用程序,它需要在用户设置的确切时间执行特定操作。为此,我使用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);

是方法问题还是我做错了??

【问题讨论】:

    标签: java android alarmmanager


    【解决方案1】:

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

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

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

    【讨论】:

    • 您使用哪个环境(Os 版本)来反映这种行为?
    • @AkshatVajpayee 我正在使用 android marshmallow 来反映这种行为。如果你想手动让你的设备进入打盹模式,你可以参考这个(developer.android.com/training/monitoring-device-state/…)
    • @JaydipKalkani 我认为这是一种解决方法,但不是完美的解决方案。只是为了让任务在准确的时间运行,我们不应该阻止操作系统进入打盹模式。您能提出其他解决方案吗?
    • @PinkeshDarji 你可以使用JobScheduler。我对 JobScheduler 不太熟悉,但我知道我们可以使用它来调度与 AlarmManager 相同的任务,并且它还为调度任务提供了额外的变体。
    • @JaydipKalkani JobScheduler 在打盹模式下推迟作业,因此如果您需要作业在准确的时间运行,这不是一个好的解决方案。
    【解决方案2】:

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

    添加权限

    <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】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-05-10
        • 1970-01-01
        • 1970-01-01
        • 2014-04-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多