StatusBarNotification как получить данные или повторно отправить намерение?

Мои приложения получают Push-уведомление через Firebase. Теперь есть 3 различных ситуации, которые могут произойти при получении уведомления:

  • Приложение находится на переднем плане
  • Приложение находится в фоновом режиме
  • Приложение не работает

Ситуация 1 не проблема. Уведомление получено в приложении в порядке. Ситуация 2 и 3 работают нормально, пока вы нажимаете уведомление в ящике. В ситуации 2 и 3, когда значок приложения отображается, а не значок ящика, приложение не получает никакого уведомления вообще. Я попытался получить активные уведомления из StatusBar, и это работает, но я не могу либо извлечь данные из Extras, либо повторно отправить уведомление в службу ожидающих push-уведомлений. Вот экспериментальный код для получения уведомлений.

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

Вопросы:

  • Правильно ли это поведение, когда приложение не получает никаких намерений, когда уведомление находится в ящике?
  • Если да, то как мне обрабатывать ситуации 2 и 3, когда пользователь нажимает значок приложения вместо уведомления ящика?

Я вижу эти данные в уведомлении het при печати всех ключей ключа Extras:

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:

Ответ 1

Хорошо, это работает для меня для всех приложений, о которых я могу думать:

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

Ответ 2

Я пробовал это:

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

Но по какой-то причине уведомление отправляется, но никогда не приходит в мое приложение.

Ответ 3

Расширяет FirebaseMessagingService и отменяет обратные вызовы onMessageReceived и onDeletedMessages. Чтобы автоматически открыть приложение/действие при получении уведомления, вам необходимо использовать атрибут data (что-то вроде {"data" : { "some_key" : "some_value"}}) в вашей полезной нагрузке, что гарантирует всегда вызывать метод FirebaseMessagingService.onMessageReceived().

Обратите внимание, что открытие активности/приложения при уведомлении без взаимодействия с пользователем действительно плохое, и его следует избегать.