Xamarin Forms - 处理通知点击

6

我有一个Xamarin Forms应用程序,它会引发Android通知,但我在创建一个简单页面时遇到了困难,该页面将与用户交互当他们点击通知时。

我知道在Xamarin.Forms中只有1个活动,因此挂起的意图必须是那个MainActivity

我将LaunchMode设置为SingleTop,并将Intent Filter设置为与pendingIntent中使用的Intent名称匹配

现在,当我点击通知时,我确实被路由到MainActivity的OnResume,但我不明白如何: 1)识别我是因为通知点击而进入这个活动-我尝试添加一个额外的挂起Intent但是我检查this.Intent.Extras时没有找到 2)即使我知道我是因为通知点击而进入该活动,如何从Activity启动特定页面。我对Xamarin很陌生,但我看不到如何导航到内容页或访问导航堆栈。

这一定是一个非常常见的用例,但我找不到任何相关的东西。

1个回答

9

请确保您在 MainActivity 中设置了 LaunchMode.SingleTop

LaunchMode.SingleTop

[Activity(~~~, LaunchMode = LaunchMode.SingleTop, ~~~]
public class MainActivity
{
   ~~~~

在您的MainActivity中(继承自FormsAppCompatActivity子类),添加OnNewIntent覆盖:

OnNewIntent:

protected override void OnNewIntent(Intent intent)
{
    base.OnNewIntent(intent);
    NotificationClickedOn(intent);
}

现在,您可以检查 intent.Action / intent.HasExtra 来确定是否是您发送的通知,并处理它。使用 Xamarin.Forms,最简单的方法是使用 MessagingCenter 发送一个消息,在您的 .NetStd/PCL Xamarin.Forms 代码库中进行订阅。

NotificationClickedOn:

void NotificationClickedOn(Intent intent)
{
    if (intent.Action == "ASushiNotification" && intent.HasExtra("MessageFromSushiHangover"))
    {
        /// Do something now that you know the user clicked on the notification...

        var notificationMessage = intent.Extras.GetString("MessageFromSushiHangover");
        var winnerToast = Toast.MakeText(this, $"{notificationMessage}.\n\n Please send 2 BitCoins to SushiHangover to process your winning ticket! ", ToastLength.Long);
        winnerToast.SetGravity(Android.Views.GravityFlags.Center, 0, 0);
        winnerToast.Show();
    }
}

发送通知示例:

void SendNotifacation()
{
    var title = "Winner, Winner, Chicken Dinner";
    var message = "You just won a million StackOverflow reputation points";

    var intent = new Intent(BaseContext, typeof(MainActivity));
    intent.SetAction("ASushiNotification");
    intent.PutExtra("MessageFromSushiHangover", message);
    var pending = PendingIntent.GetActivity(BaseContext, 0, intent, PendingIntentFlags.CancelCurrent);

    using (var notificationManager = NotificationManager.FromContext(BaseContext))
    {
        Notification notification;
        if (Android.OS.Build.VERSION.SdkInt < Android.OS.BuildVersionCodes.O)
        {
#pragma warning disable CS0618 // Type or member is obsolete
            notification = new Notification.Builder(BaseContext)
                                                        .SetContentTitle(title)
                                                        .SetContentText(message)
                                                        .SetAutoCancel(true)
                                                        .SetSmallIcon(Resource.Drawable.icon)
                                                        .SetDefaults(NotificationDefaults.All)
                                                        .SetContentIntent(pending)
                                                        .Build();
#pragma warning restore CS0618 // Type or member is obsolete
        }
        else
        {
            var myUrgentChannel = BaseContext.PackageName;
            const string channelName = "Messages from SushiHangover";

            NotificationChannel channel;
            channel = notificationManager.GetNotificationChannel(myUrgentChannel);
            if (channel == null)
            {
                channel = new NotificationChannel(myUrgentChannel, channelName, NotificationImportance.High);
                channel.EnableVibration(true);
                channel.EnableLights(true);
                channel.SetSound(
                    RingtoneManager.GetDefaultUri(RingtoneType.Notification),
                    new AudioAttributes.Builder().SetUsage(AudioUsageKind.Notification).Build()
                );
                channel.LockscreenVisibility = NotificationVisibility.Public;
                notificationManager.CreateNotificationChannel(channel);
            }
            channel?.Dispose();

            notification = new Notification.Builder(BaseContext)
                                                        .SetChannelId(myUrgentChannel)
                                                        .SetContentTitle(title)
                                                        .SetContentText(message)
                                                        .SetAutoCancel(true)
                                                        .SetSmallIcon(Resource.Drawable.icon)
                                                        .SetContentIntent(pending)
                                                        .Build();
        }
        notificationManager.Notify(1331, notification);
        notification.Dispose();
    }
}

感谢您的及时回复。OnNewIntent工作得很好。 - Nick Jones
抱歉,如果这是一个愚蠢的问题,但是一旦我订阅了一条消息并消费了它,如何在应用程序中显示一个新页面?我尝试将一个新页面推送到导航栏上,但在UI中没有任何反应。code MessagingCenter.Subscribe<ReminderOptions>(this, "Hi", (sender) => { Navigation.PushAsync(new UserPage()); }); - Nick Jones
@NickJones 你收到消息了吗?也就是说,Navigation.PushAsync 被调用了吗?而且 Navigation.PushAsync 返回一个任务,你应该等待它:await Navigation.PushAsync(..... - SushiHangover
为什么是1331?也许它是从某个示例中硬编码的标识符? - Edward Brey
@EdwardBrey,Notify方法接受一个数字值,当用户点击通知时会接收到它,因此它可以是所有通知的“硬编码”,或者可以是用作DB密钥以检索其他信息的数字值,或者用于取消具有该ID的未决通知等等。 - SushiHangover
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接