0

I have the following code. When a push notification is clicked on by the user while the app is in the background or closed, MainActivity.OnNewIntent is called but the intent is missing the extras that were put in when processing the push notification. If the app is in the foreground when the notification is clicked, the intent parameter has the extras and is properly handled.

    [Service]
    [IntentFilter(new[] {"com.google.firebase.MESSAGING_EVENT"})]
    [IntentFilter(new[] {"com.google.firebase.INSTANCE_ID_EVENT"})]
    public class MyFirebaseMessagingService : FirebaseMessagingService
    {
        public override void OnMessageReceived(RemoteMessage message)
        {
            var intent = new Intent(this, typeof(MainActivity));
            intent.PutExtra("source", "notification");
            intent.PutExtra("title", message.GetNotification()?.Title ?? "");
            intent.PutExtra("body", message.GetNotification()?.Body ?? "");
            foreach (var extra in message.Data)
            {
                intent.PutExtra(extra.Key, extra.Value);
            }
            string category = "Miscellaneous";
            if (message.Data.ContainsKey("category")
                && !string.IsNullOrWhiteSpace(message.Data["category"]))
            {
                category = message.Data["category"];
            }

            intent.AddFlags(ActivityFlags.ClearTop);
            var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.OneShot);

            var notificationBuilder = new NotificationCompat.Builder(this, category);

            notificationBuilder.SetContentTitle(message.GetNotification()?.Title)
                .SetSmallIcon(Resource.Drawable.notificationicon)
                .SetContentText(message.GetNotification()?.Body)
                .SetAutoCancel(true)
                .SetShowWhen(false)
                .SetPriority(1)
                .SetContentIntent(pendingIntent)
                .SetCategory(category)
                .SetChannelId(category);

            var notificationManager = NotificationManager.FromContext(this);

            notificationManager.Notify(0, notificationBuilder.Build());
        }
    }

And my MainActivity's OnNewIntent method looks like:

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

            if (intent.Extras != null
                && intent.Extras.ContainsKey("source")
                && "notification".Equals((string)intent.Extras.Get("source")))
            {
               this.GetLog().Info("Houston, we have liftoff!");
            }
        }

When the push notification is clicked by the user when the app is open, we hit the log message. When clicked by the user when the app is closed or in the background, it is not hit because intent.Extras is null. I can't find any articles or questions that help. Thoughts?

UPDATE:

How to handle notification when app in background in Firebase

This question got me partway there. By removing the notification object in the json when the message is sent from the server, I can now process the notification when the app is in the background. But still not when it is closed altogether.

Nathan
  • 41
  • 3
  • Did you set the MainActivity's lanch mode to `SingleTop` or `SingleTask` ? – Leo Zhu Feb 18 '21 at 01:42
  • Are you using a splashactivity? If yes you need to pass the intents through splash – Anand Feb 18 '21 at 04:08
  • @LeoZhu-MSFT I am using `SingleTask`. – Nathan Feb 18 '21 at 15:01
  • @Anand I am using a splashactivity. I just tried using the OnNewIntent there, but no luck. I **think** the service method to process the notification and create the pending intent is never being called, but I can't debug it because I have to shut down the app to test this scenario and that shuts down the debugger. – Nathan Feb 18 '21 at 15:14
  • If you use splashactivity,you could try to overwite its `OnNewIntent` ,and get the `intent.Extras` data,then pass them to the MainActivity.And set the splashactivity as the `MainLauncher`,and `SingleTask`. – Leo Zhu Feb 19 '21 at 02:39

1 Answers1

0

There were a few issues going on here.

  1. It appears part of the issue was actually server-side in creating the push notification. See here: How to handle notification when app in background in Firebase

I simply ensured that the json of the notification did not include the notification {} object and only the data {} object.

  1. I removed the splash activity (I will report back with an updated answer if I can accomplish this WITH the splash activity

  2. I used the following code:

public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
        protected override async void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            
            global::Xamarin.Forms.Forms.Init(this, savedInstanceState);

            LoadApplication(new App(GetType().Assembly, GetIntentExtras()));

            // THIS LINE IS THE KEY TO GETTING THE EXTRAS WHEN THE APP IS FIRST OPENING, SUCH AS WHEN CLICKING ON A PUSH NOTIFICATION 
            // THIS LINE'S LOCATION IS IMPORTANT- ANY HIGHER AND IT WILL NOT HAVE THE EXTRAS YET
            await ProcessIntent(Intent);
        }

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

            await ProcessIntent(intent);
        }

        private async Task ProcessIntent(Intent intent)
        {
            if (intent.Extras != null
                && intent.Extras.ContainsKey("source")
                && "notification".Equals((string)intent.Extras.Get("source")))
            {
                this.GetLog().Info("Houston, we have liftoff!");
            }
        }
    }
Nathan
  • 41
  • 3