当应用程序处于打盹模式时,警报管理器触发的Android通知不会触发

问题描述 投票:5回答:5

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

这是我希望最终不会提交的问题之一,因为在编写时会提出类似的问题。然而,有几个团队成员花了几个小时来浏览Android Developer Docs和Stackoverflow,我们似乎没有接近答案,所以我们就是这样。

如果我创建一个提醒并将其设置为在将来5分钟触发通知,则通知会正常启动。

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

例如,当用户将提醒设置为在半夜的某个时间时(可能是当用户睡着并且因此将不使用电话几个小时)时,发生通知未触发的示例。这些提醒并没有被解雇。

我目前正在尝试使用Alarm Manager完成此操作。

这个问题似乎与使用Alarm Manager's setRepeating方法的另一个问题类似,我们发现这个方法不起作用。我们使用Alarm Manager的setExactAndAllowWhileIdle方法。我们还尝试了使用Alarm Managers setAlarmClock方法的相同实现,根据Android文档“即使系统处于低功耗空闲(a.k.a. doze)模式也将允许触发”,但这也是不成功的。

我怀疑这不起作用的原因是因为当手机处于打盹模式时,setExactAndAllowWhileIdle不会触发,类似于this question中表达的问题。此问题建议使用Firebase JobDispatcher但由于这是内部通知,因此我需要使用或不使用网络连接来触发通知,这似乎会消除Firebase JobDispatcher作为选项。这个问题还表明,一旦手机退出打盹模式,用户就会收到通知,但我们从未收到通知,他们似乎因缺乏更好的条款而丢失。

我已将唤醒锁权限添加到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);
        }
    }
}
android notifications alarmmanager android-9.0-pie android-doze
5个回答
5
投票

添加意图标志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
投票

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

但是为了在确切时间触发事件,您只需要使用警报管理器。它甚至应该在打盹模式下工作。

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

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

广播接收器用于报警

public class 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重启的广播接收器并在其中再次注册您的警报。


1
投票

This is the library为我工作。


-1
投票

是的,你是对的。现在,Google建议使用WorkManager而不是AlarmManager。 AlarmManager在他的工作中有很多限制。你可以找到更多信息here (doze mode) 此外,像素手机有一个带alarmManager的bug


-1
投票

你将无法在Oreo中长时间运行后台服务,因为有行为改变,现在Oreo优化系统内存,电池等,它会杀死后台服务,解决你应该使用前台服务的问题。

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

根据我的建议,如果你可以使用FCM然后去购买它,因为像微信,Facebook使用它的应用程序,提供通知,他们没有遇到任何问题......

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

© www.soinside.com 2019 - 2024. All rights reserved.