How to handle inbound push notification message from FCM

Alwin.5974Alwin.5974 USMember ✭✭

I followed this great article xamarinhelp.com/push-notifications/ and I have managed to get my device registered with Azure/FCM and I can receive a test notification in:

public class MyFirebaseMessagingService : FirebaseMessagingService

in OnMessageReceived and then SendNotification but I can't figure out how to process that message because although this routine is called, it just does nothing:

    void SendNotification(string messageBody)
    {
        var intent = new Intent(this, typeof(MainActivity));
        intent.AddFlags(ActivityFlags.ClearTop);
        var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.OneShot);

        var notificationBuilder = new Notification.Builder(this)
                    .SetContentTitle("FCM Message")
                    .SetSmallIcon(Resource.Drawable.ic_launcher)
                    .SetContentText(messageBody)
                    .SetAutoCancel(true)
                    .SetContentIntent(pendingIntent);

        var notificationManager = NotificationManager.FromContext(this);

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

I went through the second part of the article here https://xamarinhelp.com/push-notifications-lifecycle/ which mentions different handling of the message depending on whether the app is foregrounded or backgrounded etc. but no matter what state my app is in I always get the notification in the service/SendNotification as above ie. MainActivity is never re-created, MainActivity's OnNewIntent is never called (presumably because I see no clickable banner popped from the OS).

It is confusing because that article mentions GcmServiceBase but I don't use that (I only use FirebaseMessagingService) so I don't know if I am missing some code or if that article just references an old sdk.

Best Answer

  • Alwin.5974Alwin.5974 US ✭✭
    Accepted Answer

    Thanks to the two posts above I think I've figured it out.

    My notification was working all along but I didn't realise this because there was no sound :D . Also, the Azure console test message defaults to the 'data' type so that is why it always triggered OnMessageReceived (explained below). Here is how I found it to work with the different message types:

    1. Notification message:

      • App in foreground: OnMessageReceived is fired, notification must be handled manually
      • App in Background: Android handles the notification (shown in task bar)
      • App closed: Couldn't test in debug
    2. Data Message:

      • App in foreground or Background: OnMessageReceived is fired, notification must be handled manually
      • App closed: Couldn't test in debug but I read that OnMessageReceived is fired in this case

    When the notification from above (shown either by the OS or by a manual call to notificationManager.Notify) is clicked then MainActivity executes:

    • App in Background: OnCreate executes and the message is handled by something like this:

      protected override void OnCreate(Bundle bundle)
      {
          //Startup code goes here
      
          if (Intent.Extras != null)
          {
              foreach (var key in Intent.Extras.KeySet())
              {
                  if (key != null)
                  {
                      var value = Intent.Extras.GetString(key);
                  }
              }
          }
      
      }
      
    • App in Foreground: OnNewIntent executes and the message is handled by something like this (I am not sure if this is due to LaunchMode = LaunchMode.SingleTop being set on MainActivity):

      protected override void OnNewIntent(Intent intent)
      {
          if (intent != null)
          {
              var message = intent.GetStringExtra("message");
      
              if (!string.IsNullOrEmpty(message))
              {
                  // Do something
              }
          }
      } 
      

Answers

  • AlanStrattonAlanStratton USMember ✭✭

    GCM refers to Google Cloud Messaging. Firebase is just their newest version which is what you should use. So any reference to GCMServiceBase is old code.

    I'm a bit confused as to what your problem is. You say your device registers and gets notifications, but your sendNotification does nothing? The "SendNotification" is what displays the message as a notification, so it must be working if you are getting notifications. In the "OnMessageReceived" method, you can decide if the notification is silent, or if you want to notify the end user by calling "SendNotification".

    In my "OnMessageReceived" i have this code:

    int SDK_INT = (int)Android.OS.Build.VERSION.SdkInt;
    if (SDK_INT < 26)
    {
    SendNotification2(messageBody);
    }
    else
    {
    SendNotification(messageBody);
    }

    Which allows me to support multiple notification styles depending on the version of Android. Below is my code for notifications above SDK 25. (it is different)

        void SendNotification(string messageBody)
        {
            var intent = new Intent(this, typeof(MainActivity));
            intent.AddFlags(ActivityFlags.ClearTop);
            var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.OneShot);
            string CHANNEL_ID = "my_channel_01";
    
            var notificationBuilder = new Notification.Builder(this, CHANNEL_ID)
                .SetSmallIcon(Resource.Drawable.icon)
                .SetContentTitle("New Todo Item")
                .SetContentText(messageBody)
                .SetContentIntent(pendingIntent)
                 .SetAutoCancel(true);
    
            var notificationManager = NotificationManager.FromContext(this);
    
            NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID,"Test Channel",NotificationImportance.Low);
            // Configure the notification channel.
            mChannel.Description = "My Notification Channel Description";
    
            mChannel.EnableLights(true);
    
            mChannel.EnableVibration(true);
            mChannel.SetVibrationPattern(new long[] { 100, 200, 300, 400, 500, 400, 300, 200, 400 });
    
    
            notificationManager.CreateNotificationChannel(mChannel);
            notificationManager.Notify(1, notificationBuilder.Build());
        }
    
  • AdamMeaneyAdamMeaney USMember ✭✭✭✭✭

    https://github.com/CrossGeeks/FirebasePushNotificationPlugin works to receive Firebase notifications pretty well.

    Or at least can show example code for how to properly handle it.

  • Alwin.5974Alwin.5974 USMember ✭✭
    Accepted Answer

    Thanks to the two posts above I think I've figured it out.

    My notification was working all along but I didn't realise this because there was no sound :D . Also, the Azure console test message defaults to the 'data' type so that is why it always triggered OnMessageReceived (explained below). Here is how I found it to work with the different message types:

    1. Notification message:

      • App in foreground: OnMessageReceived is fired, notification must be handled manually
      • App in Background: Android handles the notification (shown in task bar)
      • App closed: Couldn't test in debug
    2. Data Message:

      • App in foreground or Background: OnMessageReceived is fired, notification must be handled manually
      • App closed: Couldn't test in debug but I read that OnMessageReceived is fired in this case

    When the notification from above (shown either by the OS or by a manual call to notificationManager.Notify) is clicked then MainActivity executes:

    • App in Background: OnCreate executes and the message is handled by something like this:

      protected override void OnCreate(Bundle bundle)
      {
          //Startup code goes here
      
          if (Intent.Extras != null)
          {
              foreach (var key in Intent.Extras.KeySet())
              {
                  if (key != null)
                  {
                      var value = Intent.Extras.GetString(key);
                  }
              }
          }
      
      }
      
    • App in Foreground: OnNewIntent executes and the message is handled by something like this (I am not sure if this is due to LaunchMode = LaunchMode.SingleTop being set on MainActivity):

      protected override void OnNewIntent(Intent intent)
      {
          if (intent != null)
          {
              var message = intent.GetStringExtra("message");
      
              if (!string.IsNullOrEmpty(message))
              {
                  // Do something
              }
          }
      } 
      
  • BillyLiuBillyLiu Member, Xamarin Team Xamurai

    @Alwin.5974

    I'm glad your problem is solved. Please mark your reply as the answer, so that can help other people who have the same issue.

Sign In or Register to comment.