应用程序处于打ze模式时,由警报管理器触发的Android通知未触发

时间:2019-04-05 17:44:44

标签: android notifications alarmmanager android-9.0-pie android-doze

我有以下要求。用户需要能够在我的应用中安排定期提醒,该提醒将在每天的确切时间触发推送通知。

这是我希望最终不要提交的那些问题之一,因为在编写该问题时建议使用类似的问题。但是,几个团队成员花了很多时间来查看Android Developer Docs和Stackoverflow,我们似乎离答案还很近,所以我们到了。

如果我创建提醒并将其设置为在未来5分钟内触发通知,则可以正常触发通知。

我怀疑这可能是由Android P中引入的省电,唤醒锁等更改引起的问题,因为在将目标SDK更新到28之前我们没有这个问题。这是唯一的问题,但我可以始终在运行Android P的Pixel和Pixel 3 XL上重现该问题。

例如,当用户将提醒设置为半夜的某个时间(大概是在用户处于睡眠状态,因此将有几个小时不使用电话)时,发生通知不触发的示例。这些提醒从未触发过。

我目前正在尝试使用“警报管理器”来完成此操作。

此问题似乎类似于另一个使用Alarm Manager's setRepeating方法的问题,我们发现该方法不起作用。相反,我们使用警报管理器的setExactAndAllowWhileIdle方法。我们还使用Alarm Managers setAlarmClock方法尝试了相同的实现,根据Android文档,该方法“即使系统处于低功率空闲(即打ze)模式,也将被允许触发”,但这还是没有成功

我怀疑这不起作用的原因是因为在电话处于打ze模式时,setExactAndAllowWhileIdle不会触发,类似于this question中表示的问题。此问题建议使用Firebase JobDispatcher,但由于这是内部通知,因此无论是否具有网络连接,我都需要触发该通知,这似乎消除了Firebase JobDispatcher的选择。这个问题还表明,一旦手机退出打ze模式,用户会收到通知,但我们从未收到通知,他们似乎因为缺少更好的条件而迷路了。

我已将唤醒锁定权限添加到我的AndroidManifest.xml中:

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

这是我的接收者在AndroidManifest.xml中的注册方式

<receiver android:name="com.myapp.receiver.AlarmReceiver">
    </receiver>

这是我当前的实现方式:

待处理通知的意图

Intent i = new Intent(context, ScheduleAllReceiver.class);
    PendingIntent scheduleAllPendingIntent = PendingIntent.getBroadcast(context, SCHEDULER_DAILY_ALL, i, PendingIntent.FLAG_UPDATE_CURRENT);

我随后按如下方式调用方法“ createAlarm”

createAlarm(context, scheduleAllPendingIntent, calendar.getTimeInMillis());

创建警报

public static void createAlarm(Context context, PendingIntent pendingIntent, long timeinMilli) {
    AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);

    if(alarmManager != null) {

        if (Build.VERSION.SDK_INT >= 23) {
            alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, timeinMilli, pendingIntent);
        } else {
            alarmManager.setExact(AlarmManager.RTC_WAKEUP, timeinMilli, pendingIntent);
        }
    }
}

5 个答案:

答案 0 :(得分:4)

添加意图标志 FLAG_RECEIVER_FOREGROUND

https://developer.android.com/reference/android/content/Intent#FLAG_RECEIVER_FOREGROUND在致电广播接收器之前应该可以解决问题

Intent intent = new Intent(context, ScheduleAllReceiver.class);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
PendingIntent scheduleAllPendingIntent = PendingIntent.getBroadcast(context, SCHEDULER_DAILY_ALL, intent, PendingIntent.FLAG_UPDATE_CURRENT);

答案 1 :(得分:1)

我也遇到过类似的问题。我试过工作经理,但结果是一样的。当手机锁定并处于打ze模式时,不会触发该事件。

但是要在准确的时间触发事件,您只需要使用警报管理器。即使在打ze模式下也应该可以使用。

注册警报管理器的方法(使用设置的确切时间而不是重复)

public static void registerAlarm(Context context){
    final int FIVE_MINUTES_IN_MILLI = 300000;
    final int THIRTY_SECOND_IN_MILLI = 30000;
    long launchTime = System.currentTimeMillis() + FIVE_MINUTES_IN_MILLI;
    AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    Intent i = new Intent(context, BroadcastAlarmManger.class);
    PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
        am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, launchTime, pi);
    else am.setExact(AlarmManager.RTC_WAKEUP, launchTime, pi);
    Utility.printLog("timestamp "+launchTime);
}

广播警报接收器

公共类BroadcastAlarmManger扩展了BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
    //register alarm again
     registerAlarm(context);
    .
    .
    .
    .
    //do your stuff    
}

清单声明

<receiver
        android:name="com.taxiemall.utility.BroadcastAlarmManger"
        android:enabled="true"
        android:exported="true"/>

此外,您还必须手动处理重新启动。每次重新启动后,已清除的已清除警报。因此,为Android重启注册一个广播接收器,然后在其中重新注册警报。

答案 2 :(得分:1)

This is the library对我有用。

答案 3 :(得分:-1)

是的,您是对的。 现在,Google建议使用WorkManager代替AlarmManager。 AlarmManager在他的工作中有很多限制。您可以找到更多信息here (doze mode)
此外,像素电话的bug带有AlarmManager

答案 4 :(得分:-1)

由于行为更改,您将无法运行长时间在Oreo中运行的后台服务,现在Oreo可以优化系统内存,电池等,这会杀死后台服务,要解决您的问题,您应该使用前台服务。

看看后台执行限制https://developer.android.com/about/versions/oreo/android-8.0-changes

我的建议是,如果您可以使用FCM,那就去做吧,因为微信之类的应用程序,Facebook都在使用它来传递通知,而他们不会遇到任何问题...

希望这有助于理解问题。...