状态栏通知如何获取数据或重新发送意图?

13

我的应用程序通过Firebase接收推送通知。现在当通知到达时,会发生3种不同的情况:

  1. 应用程序在前台
  2. 应用程序在后台
  3. 应用程序未运行

情况1没有问题。通知可以正常在应用程序中接收到。 只要在情况2和情况3中您点击抽屉中的通知,它们就可以很好地工作。 但是,在情况2和情况3中,如果点击应用程序图标而不是抽屉图标,应用程序将无法接收任何通知。我试图从状态栏中获取活动通知并且可以成功,但我无法从Extras中检索数据或重新发送通知以等待推送通知服务。以下是用于获取通知的实验性代码。

        NotificationManager notificationManager = (NotificationManager)Application.Context.GetSystemService(Context.NotificationService);

        var notifications = notificationManager.GetActiveNotifications()
            .Where(notif => notif.PackageName == Application.Context.PackageName);

        foreach (var notification in notifications)
        {
            Log.Info(TAG, "OnActivityResumed: Notification in active in Status Bar: {0}", notification.Notification.ToString());

            var data = notification.Notification.Extras.GetString("data");

            Log.Debug("Notifier", "Data received: {0}", data);

            //if (data != null)
            //{
            //    Settings.Notification = JsonConvert.DeserializeObject<LoginNotificationParameter>(data);
            //}
        }

        // Canceling all notifications
        notificationManager.CancelAll();

问题:

  1. 当通知在抽屉中时,应用程序不接收任何意图是否是正确的行为?
  2. 如果是这样的话,当用户点击应用程序图标而不是抽屉通知时,我该如何处理情况2和3?

在打印所有额外键值时,我可以在通知中看到这些数据:

06-28 16:34:13.174 20792 20792 I Notifier: OnActivityResumed: Notification is active in Status Bar: Notification(pri=0 contentView=null vibrate=null sound=content://settings/system/notification_sound defaults=0x0 flags=0x10 color=0x00000000 vis=PRIVATE semFlags=0x0 semPriority=0)
06-28 16:34:13.191 20792 20792 I Notifier: KeyIn: Extras Key: android.title Data: Login
06-28 16:34:13.191 20792 20792 I Notifier: KeyIn: Extras Key: android.subText Data:
06-28 16:34:13.191 20792 20792 I Notifier: KeyIn: Extras Key: android.template Data: android.app.Notification$BigTextStyle
06-28 16:34:13.192 20792 20792 I Notifier: KeyIn: Extras Key: android.showChronometer Data: false
06-28 16:34:13.192 20792 20792 I Notifier: KeyIn: Extras Key: android.text Data: Er is een inlogverzoek voor u ontvangen.
06-28 16:34:13.194 20792 20792 I Notifier: KeyIn: Extras Key: android.progress Data: 0
06-28 16:34:13.194 20792 20792 I Notifier: KeyIn: Extras Key: android.progressMax Data: 0
06-28 16:34:13.195 20792 20792 I Notifier: KeyIn: Extras Key: android.appInfo Data: ApplicationInfo{a27f281 nl.natuurnetwerk.notifier}
06-28 16:34:13.195 20792 20792 I Notifier: KeyIn: Extras Key: android.showWhen Data: true
06-28 16:34:13.195 20792 20792 I Notifier: KeyIn: Extras Key: android.largeIcon Data:
06-28 16:34:13.195 20792 20792 I Notifier: KeyIn: Extras Key: android.bigText Data: Er is een inlogverzoek voor u ontvangen.
06-28 16:34:13.195 20792 20792 I Notifier: KeyIn: Extras Key: android.infoText Data:
06-28 16:34:13.195 20792 20792 I Notifier: KeyIn: Extras Key: android.originatingUserId Data: 0
06-28 16:34:13.196 20792 20792 I Notifier: KeyIn: Extras Key: android.progressIndeterminate Data: false
06-28 16:34:13.196 20792 20792 I Notifier: KeyIn: Extras Key: android.remoteInputHistory Data:

你是否想通过通知来更新应用程序中的数据? - pinedax
该应用程序的功能是验证网站登录。当用户使用UserId/Password登录特定网站时,会向应用程序发送通知。当应用程序打开时,它开始扫描在网站登录后显示的QR码。通知中的信息必须与QR码中的信息相等。当匹配时,网站将继续进入其主页。否则,登录将被拒绝。 - Paul Sinnema
3个回答

7

好的,对于我能想到的所有应用程序状态,这种方式都适用:

using Android.App;
using Android.Content;
using Android.OS;
using MvvmCross.Droid.Platform;
using MvvmCross.Droid.Support.V4;

namespace Notifier.Android.Classes.Services
{
    /// <summary>
    /// This class receives all Firebase intents.
    /// </summary>
    [BroadcastReceiver(Enabled = true, Permission = "com.google.android.c2dm.permission.SEND")]
    [IntentFilter(new[] { "com.google.android.c2dm.intent.RECEIVE" }, Categories = new string[] { "com.yourdomain.yourapp" })]
    public class FirebaseBroadcastReceiver : MvxWakefulBroadcastReceiver
    {
        public override void OnReceive(Context context, Intent intent)
        {
            var setup = MvxAndroidSetupSingleton.EnsureSingletonAvailable(context);
            setup.EnsureInitialized();

            var service = new Intent(context, typeof(FirebaseBroadcastReceiver));

            PowerManager.WakeLock sWakeLock;
            var pm = PowerManager.FromContext(context);
            sWakeLock = pm.NewWakeLock(WakeLockFlags.Full, "FirebaseBroadcastReceiver");
            sWakeLock.Acquire();


            if (intent.Extras != null)
            {
                // Your code to handle the intent
            }

            sWakeLock.Release();

            StartWakefulService(context, service);
        }
    }
}

1
继承FirebaseMessagingService并重写onMessageReceivedonDeletedMessages回调。要在收到通知时自动打开应用程序/活动,需要在有效负载中使用data(类似于{"data" : { "some_key" : "some_value"}})属性,这保证始终调用FirebaseMessagingService.onMessageReceived()方法。
请注意,未经用户交互即在通知上打开活动/应用程序确实很糟糕,应尽量避免。

@Paul Sinnema:我的答案是针对Android的,你可以根据Xamarin中可用的等效类来调整答案。 - Mahendra Liya
这正是我实现它的方式。问题在于当应用程序在后台运行时,用户点击图标而不是托盘通知时,不会收到任何通知,我们必须自己找到它。如我自己的答案中所示,WakefulBroadcastReceiver 可以很好地解决这个问题。 - Paul Sinnema

1
我尝试过这个:

    private void HandlePendingNotifications()
    {
        NotificationManager notificationManager = (NotificationManager)Application.Context.GetSystemService(Context.NotificationService);

        var notifications = notificationManager.GetActiveNotifications()
            .OrderByDescending(notif => notif.PostTime)
            .Where(notif => notif.PackageName == Application.Context.PackageName);

        var notification = notifications.FirstOrDefault();

        if (notification != null)
        {
            Log.Debug(TAG, "OnActivityResumed: Notification is active in Status Bar: {0}", notification.Notification.ToString());

            NotificationManagerCompat nm = NotificationManagerCompat.From(this);

            notification.Notification.Sound = null;
            notification.Notification.Vibrate = null;

            // nm.Cancel(notification.Id);
            nm.Notify(0, notification.Notification);
        }

        //Timer timer = new Timer((state) =>
        //{
        //    // Canceling all notifications
        //    notificationManager.CancelAll();
        //    timer = null;
        //}, null, 2000, 2000);
    }

但出于某种原因,通知已发送,但从未到达我的应用程序。


新发送的通知显示在抽屉中,但点击它不会激活我的应用程序。 - Paul Sinnema
在Notify()之后,抽屉中有两个通知。一个是原始的通知,另一个是我发送的通知。原始的通知会激活我的应用程序,而第二个通知则不会。 - Paul Sinnema

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