简体   繁体   English

警报管理器的 setExactAndAllowWhileIdle() 无法正常工作

[英]setExactAndAllowWhileIdle() for alarmmanager is not working properly

I am developing an app which needs to perform particular action on the exact time which user has set.我正在开发一个需要在用户设置的确切时间执行特定操作的应用程序。 For this i am using setExactAndAllowWhileIdle() method because this documentation says that android devices having android 6.0 or above has doze mode concept in which if devices remains idle for some times then it will enter into doze mode and doze mode restricts alarms.为此,我使用setExactAndAllowWhileIdle()方法,因为该文档说具有 android 6.0 或更高版本的 android 设备具有打盹模式概念,其中如果设备保持空闲一段时间,则它将进入打瞌睡模式并且打瞌睡模式会限制警报。 If i want to fire my alarm when device is into doze mode then i have setExactAndAllowWhileIdle() method as documentation says.如果我想在设备进入打盹模式时触发警报,那么我已经按照文档说明设置了setExactAndAllowWhileIdle()方法。 This documentation also contains manual way to enter device into doze mode for testing purpose.本文档还包含将设备进入休眠模式以进行测试的手动方法。 so, i am testing using that way but my alarm is not fired when device is into doze mode and when i stops doze mode via terminal command my past alarm will fires instantly.所以,我正在使用这种方式进行测试,但是当设备进入瞌睡模式时我的警报不会触发,当我通过终端命令停止瞌睡模式时,我过去的警报将立即触发。

So, my problem is that setExactAndAllowWhileIdle() this method is not working in doze mode but it should have to work as said in documentation.所以,我的问题是setExactAndAllowWhileIdle()这个方法在打盹模式下不起作用,但它应该像文档中所说的那样工作。 I know limitation of this method that i can only fire one alarm per 9 minutes and i am following this rule.我知道这种方法的局限性,即每 9 分钟只能触发一个警报,并且我遵循此规则。 So, i can't understand where is the problem.所以,我不明白问题出在哪里。

My Code:我的代码:

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

Is it a method problem or i am doing it in a wrong way??是方法问题还是我做错了??

I've found the solution for my problem so, i am posting my own answer here which worked for me.我已经找到了我的问题的解决方案,所以我在这里发布了我自己的答案,这对我有用。

Using setAlarmClock() method has solved my problem.使用setAlarmClock()方法解决了我的问题。 If you set alarm using setAlarmClock() method then this will not allow the system to go into doze mode before 1 hour of your alarm's time.如果您使用 setAlarmClock() 方法设置闹钟,那么这将不允许系统在闹钟时间 1 小时之前进入打盹模式。 I had tested this by manually forcing my device to go into doze mode after setting my alarm.我已经通过在设置闹钟后手动强制我的设备进入打盹模式来测试这一点。 Let me explain full scenario.让我解释一下完整的场景。

  1. First of all i set alarm after 5 minutes from current time and then tried to putting my device into doze mode manually by using following command.首先,我在距离当前时间 5 分钟后设置了警报,然后尝试使用以下命令手动将我的设备置于打盹模式。

adb shell dumpsys deviceidle force-idle adb shell dumpsys deviceidle force-idle

It Shows它显示

unable to enter into doze mode无法进入打瞌睡模式

  1. After that i set alarm after 1 hour and 1 minute from current time and then i have tried to put my device into doze mode and it enters into doze mode successfully.在那之后,我在从当前时间起 1 小时 1 分钟后设置了警报,然后我尝试将我的设备置于打盹模式并成功进入打盹模式。 Then i have done nothing on my device and it fires alarm exactly on time even it was in a doze mode.然后我在我的设备上什么也没做,即使它处于打盹模式,它也能准时发出警报。

Hence, i conclude that setAlarmClock() method prevents your device from entering to doze mode if there is a small amount of timestamp between current time and your alarm time.因此,我得出结论,如果当前时间和闹钟时间之间存在少量时间戳,则 setAlarmClock() 方法会阻止您的设备进入打盹模式。 Otherwise if your device is already in doze mode then it will gets exit from doze mode before some time of your alarm so, your alarm works fine.否则,如果您的设备已经处于打盹模式,那么它会在闹钟响起之前退出打盹模式,因此,您的闹钟工作正常。

Updated code:更新代码:

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

you can whitelist your app from doze mode by ignoring battery optimizations..您可以通过忽略电池优化将您的应用程序从打盹模式列入白名单。

Add permission添加权限

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

request whitelist your app请求将您的应用列入白名单

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

Note: Neither setAndAllowWhileIdle() nor setExactAndAllowWhileIdle() can fire alarms more than once per 15 minutes per app.注意:对于每个应用,无论是 setAndAllowWhileIdle() 还是 setExactAndAllowWhileIdle() 都不能每 15 分钟触发一次以上的警报。

Some addition to @MarGin's answer.对@MarGin 的回答的一些补充。
It's much easier for user to do all in one dialog but this violates the Google Play policy用户在一个对话框中完成所有操作要容易得多,但这违反了 Google Play 政策

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM