PendingInent 创建的 Android 任务无法再次使用 pendingIntent 启动另一个活动

Posted

技术标签:

【中文标题】PendingInent 创建的 Android 任务无法再次使用 pendingIntent 启动另一个活动【英文标题】:Android Task Created by PendingInent cannot start another activity with pendingIntent again 【发布时间】:2021-12-26 01:26:36 【问题描述】:

我有 2 个活动:主要(将与警报管理器安排通知)和消息(处理用户导航或通知)。 Message 上没有设置启动模式和标志。消息由用户导航或通知打开。

正常的控制流程:

(主屏幕) -> (user) -> Main 的新任务 -> (user) -> new Message -> (notification) -> new Message -> (notification) -> new Message -> (用户)-> 新消息

当应用程序未加载并且通过消息通知启动新任务时。流程没问题:

(主屏幕)->(通知)-> 消息的新任务 ->(用户)-> 新消息

当第二个通知被点击时,问题就出现了,它没有被正确处理。第二个通知预计会有新消息。

(主屏幕)->(通知)-> 消息的新任务 ->(通知)-> X 现在什么都没有,但期待新消息

最后一个通知未决意图无法启动消息(没有 OnCreate,没有 OnNewIntent)。也没有新的任务开始处理它。如果任务在后台,通知挂起意图将把任务带到前台(但没有新的活动)。结果是,对于由挂起意图启动的任务,任何进一步的挂起意图都不会创建新的活动。不确定这是否与未决的意图安全问题或其他问题有关。

当任务由待定意图启动时,如何启动带有通知待定意图的新活动消息?任何帮助将不胜感激。

谢谢,

尼克

代码是用 Xamarin 编写的,供参考:

设置闹钟的代码,context就是Activity的上下文。

    Intent intentScheduleReminder = new Intent(context, typeof(BroadcastReceiver));
    intentScheduleReminder.SetAction(PlatformConstants.NotificationActionShow);
    intentScheduleReminder.PutExtra(PlatformConstants.ScheduleReminderId, scheduleReminder.Id);
    PendingIntent intentAlarm = PendingIntent.GetBroadcast(context, scheduleReminder.Id, intentScheduleReminder, PendingIntentFlags.CancelCurrent);

    Java.Util.Calendar calendar = DroidUtility.ConvertDateTimeToCalendar(scheduleReminder.ScheduleDateTime);
    AlarmManager alarmManager = (AlarmManager)Application.Context.GetSystemService(Context.AlarmService);
    alarmManager.SetExactAndAllowWhileIdle(AlarmType.RtcWakeup, calendar.TimeInMillis, intentAlarm);

发送通知的代码。 Pending Intent 是使用 BroadcastReceiver.OnReceive 的上下文创建的

    var builder = new NotificationCompat.Builder(Application.Context,  PlatformConstants.NotificationChannelIdBillReminder)
        .SetContentTitle(appNotification.Title)
        .SetContentText(appNotification.Message)
        .SetSmallIcon(Resource.Drawable.ic_appicon_24dp)
        .SetLargeIcon(largeIconBitmap)
        .SetAutoCancel(true)
        .SetOnlyAlertOnce(true);
    Intent intent = new Intent((Context)BroadcastContext, typeof(InfiniteScrollingParentFsActivity));
    intent.PutExtra(……
    PendingIntent pendingIntent = PendingIntent.GetActivity((Context)BroadcastContext, notificationId, intent, 0);
    builder.SetContentIntent(pendingIntent);
    Notification notification = builder.Build();
    NotificationManager notificationManager = (NotificationManager)Application.Context.GetSystemService(Context.NotificationService);
    notificationManager.Notify(notificationId, notification);

【问题讨论】:

【参考方案1】:

仔细阅读the documentation for PendingIntent。尤其是这部分:

由于这种行为,重要的是要知道两个 Intent 何时被认为是相同的,以便检索 PendingIntent。人们犯的一个常见错误是创建多个 PendingIntent 对象,其 Intent 仅在其“额外”内容上有所不同,期望每次都获得不同的 PendingIntent。这不会发生。 Intent 中用于匹配的部分与 Intent.filterEquals 定义的部分相同。如果您使用两个根据 Intent.filterEquals 等效的 Intent 对象,那么您将获得相同的 PendingIntent。

您的通知总是触发相同的 Intent:

Intent intent = new Intent((Context)BroadcastContext, typeof(InfiniteScrollingParentFsActivity));
intent.PutExtra(……
PendingIntent pendingIntent = PendingIntent.GetActivity((Context)BroadcastContext, notificationId, intent, 0);

因此,如果存在相同的 Activity,它总是会重新打开它。

您可能希望使您的意图独一无二,以便每个意图都代表一条消息。您可以通过为意图的 data 字段设置一个唯一值来做到这一点:

Intent intent = new Intent((Context)BroadcastContext, typeof(InfiniteScrollingParentFsActivity));
intent.PutExtra(……

intent.SetData(something that uniquely ids this message here) <----

PendingIntent pendingIntent = PendingIntent.GetActivity((Context)BroadcastContext, notificationId, intent, 0);

【讨论】:

以上是关于PendingInent 创建的 Android 任务无法再次使用 pendingIntent 启动另一个活动的主要内容,如果未能解决你的问题,请参考以下文章

android的LitePal数据库如何动态创建表

androidstudio怎么创建LearnKotlin

Android:在android中反复创建这样的xml Layout?

android教程:Android创建新项目及开发

Android studio怎么创建一个Java类文件

创建Android守护进程(底层服务)