Open contentpage when tap push notification using FirebasePushNotificationPlugin

SreeeeSreeee ✭✭✭✭✭INMember ✭✭✭✭✭

I am using the following notification payload for sending push notification to my android device using postman.

{
    "to" : "device_key",
 "collapse_key" : "type_a",
 "notification" : {
     "body" : "Body of Your Notification",
     "title": "Title of Your Notification",
     "sound": "default"
 },
 "data" : {
     "body" : "Body of Your Notification in Data",
     "title": "Title of Your Notification in Title",
     "key_1" : "Value for key_1",
     "key_2" : "Value for key_2"
 }
}

Notifications are received to my device and OnMessageReceived() triggered only when the app is in the foreground. When the app is in background state OnMessageReceived is not triggering and not triggering when tapping the notification.

I installed FirebasePushNotificationPlugin and added notification events in App constructor like below.

CrossFirebasePushNotification.Current.OnNotificationReceived += (s, p) =>
{
      System.Diagnostics.Debug.WriteLine("Received");
};

CrossFirebasePushNotification.Current.OnNotificationOpened += (s, p) =>
{
    System.Diagnostics.Debug.WriteLine("Opened");
    foreach (var data in p.Data)
     {
         System.Diagnostics.Debug.WriteLine($"{data.Key} : {data.Value}");
     }
     if (!string.IsNullOrEmpty(p.Identifier))
     {
         System.Diagnostics.Debug.WriteLine($"ActionId: {p.Identifier}");
     }
 };

But when receiving or tapping notification these codes are not triggering.

In one thread I found that above events are triggered when you send data message only, should not be sent notification messages if you want to use this event handler.

But if I send data messages only the notifications are not received to my device. Following is the notification payload for data messages.

{
    "to" : "device_key",
 "collapse_key" : "type_a",
 "data" : {
     "body" : "Body of Your Notification in Data",
     "title": "Title of Your Notification in Title",
     "key_1" : "Value for key_1",
     "key_2" : "Value for key_2"
 }
}

I need to open a content page in the PCL when tapping a notification. But OnNotificationReceived or OnNotificationOpened are not triggering. So what I am missing in this implementation?

Best Answer

  • SreeeeSreeee ✭✭✭✭✭ IN ✭✭✭✭✭
    edited April 29 Accepted Answer

    I handle the notification tapping in following way. The page is loading is handled in App.xaml.cs.

    On OnCreate():

    //Background or killed mode
                if (Intent.Extras != null)
                {
                    foreach (var key in Intent.Extras.KeySet())
                    {
                        var value = Intent.Extras.GetString(key);
                        if (key == "webContentList") 
                        {
                            if (value?.Length > 0)
                            {
                                isNotification = true;
                                LoadApplication(new App(domainname, value));
                            }
                        }
                    }
                }
                //Foreground mode
                if (FirebaseNotificationService.webContentList.ToString() != "")
                {
                    isNotification = true;
                    LoadApplication(new App(domainname, FirebaseNotificationService.webContentList.ToString()));
                    FirebaseNotificationService.webContentList = "";
                }
    
                //Normal loading
                if (!isNotification)
                {
                    LoadApplication(new App(domainname, string.Empty));
                }
    

    On FirebaseNotificationService:

    [Service]
    [IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
    public class FirebaseNotificationService : FirebaseMessagingService
    {
        public static string webContentList = "";
        public override void OnMessageReceived(RemoteMessage message)
        {
            base.OnMessageReceived(message);
            webContentList = message.Data["webContentList"];
    
            try
            {
                SendNotificatios(message.GetNotification().Body, message.GetNotification().Title);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error:>>" + ex);
            }
        }
    
        public void SendNotificatios(string body, string Header)
        {
            if (Build.VERSION.SdkInt < BuildVersionCodes.O)
            {
                var intent = new Intent(this, typeof(MainActivity));
                intent.AddFlags(ActivityFlags.ClearTop);
                var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.OneShot);
    
                var notificationBuilder = new Android.App.Notification.Builder(this, Utils.CHANNEL_ID)
                            .SetContentTitle(Header)
                            .SetSmallIcon(Resource.Drawable.icon)
                            .SetContentText(body)
                            .SetAutoCancel(true)
                            .SetContentIntent(pendingIntent);
    
                var notificationManager = NotificationManager.FromContext(this);
    
                notificationManager.Notify(0, notificationBuilder.Build());
            }
            else
            {
                var intent = new Intent(this, typeof(MainActivity));
                intent.AddFlags(ActivityFlags.ClearTop);
                var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.OneShot);
    
                var notificationBuilder = new Android.App.Notification.Builder(this, Utils.CHANNEL_ID)
                            .SetContentTitle(Header)
                            .SetSmallIcon(Resource.Drawable.icon)
                            .SetContentText(body)
                            .SetAutoCancel(true)
                            .SetContentIntent(pendingIntent)
                            .SetChannelId(Utils.CHANNEL_ID);
    
                if (Build.VERSION.SdkInt < BuildVersionCodes.O)
                {
                    return;
                }
    
                var channel = new NotificationChannel(Utils.CHANNEL_ID, "FCM Notifications", NotificationImportance.High)
                {
                    Description = "Firebase Cloud Messages appear in this channel"
                };
    
                var notificationManager = (NotificationManager)GetSystemService(NotificationService);
                notificationManager.CreateNotificationChannel(channel);
    
                notificationManager.Notify(0, notificationBuilder.Build());
            }
        }
    

Answers

  • LandLuLandLu Xamurai Member, Xamarin Team Xamurai

    Refer to this documentation: https://firebase.google.com/docs/cloud-messaging/android/receive#sample-receive
    If your payload contains both notification and data keys, the data information could be retrieved via the intent's extras when your app is on the background state.
    So you could place an if statement in your Activity's OnCreate when you find its extras is not null, it means the user tap the notification to open your app. Then you could handle your message received event there:

    protected override void OnCreate(Bundle savedInstanceState)
    {
        TabLayoutResource = Resource.Layout.Tabbar;
        ToolbarResource = Resource.Layout.Toolbar;
    
        base.OnCreate(savedInstanceState);
        global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
        Microsoft.WindowsAzure.MobileServices.CurrentPlatform.Init();
        LoadApplication(new App());
    
        var extra = Intent.Extras;
        if (extra != null)
        {
            var key1 = extra.GetString("key_1");
            // Retrieve other keys
            // Use Messaging to inform Forms App to change the content
        }                
    }
    

    And I've tested it on CrossFirebasePushNotification the OnNotificationOpened will be triggered when the user click notification to open this app even though this message contains data and notification.

  • SreeeeSreeee ✭✭✭✭✭ INMember ✭✭✭✭✭

    @LandLu I will go through this and update you.

  • SreeeeSreeee ✭✭✭✭✭ INMember ✭✭✭✭✭
    edited April 29 Accepted Answer

    I handle the notification tapping in following way. The page is loading is handled in App.xaml.cs.

    On OnCreate():

    //Background or killed mode
                if (Intent.Extras != null)
                {
                    foreach (var key in Intent.Extras.KeySet())
                    {
                        var value = Intent.Extras.GetString(key);
                        if (key == "webContentList") 
                        {
                            if (value?.Length > 0)
                            {
                                isNotification = true;
                                LoadApplication(new App(domainname, value));
                            }
                        }
                    }
                }
                //Foreground mode
                if (FirebaseNotificationService.webContentList.ToString() != "")
                {
                    isNotification = true;
                    LoadApplication(new App(domainname, FirebaseNotificationService.webContentList.ToString()));
                    FirebaseNotificationService.webContentList = "";
                }
    
                //Normal loading
                if (!isNotification)
                {
                    LoadApplication(new App(domainname, string.Empty));
                }
    

    On FirebaseNotificationService:

    [Service]
    [IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
    public class FirebaseNotificationService : FirebaseMessagingService
    {
        public static string webContentList = "";
        public override void OnMessageReceived(RemoteMessage message)
        {
            base.OnMessageReceived(message);
            webContentList = message.Data["webContentList"];
    
            try
            {
                SendNotificatios(message.GetNotification().Body, message.GetNotification().Title);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error:>>" + ex);
            }
        }
    
        public void SendNotificatios(string body, string Header)
        {
            if (Build.VERSION.SdkInt < BuildVersionCodes.O)
            {
                var intent = new Intent(this, typeof(MainActivity));
                intent.AddFlags(ActivityFlags.ClearTop);
                var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.OneShot);
    
                var notificationBuilder = new Android.App.Notification.Builder(this, Utils.CHANNEL_ID)
                            .SetContentTitle(Header)
                            .SetSmallIcon(Resource.Drawable.icon)
                            .SetContentText(body)
                            .SetAutoCancel(true)
                            .SetContentIntent(pendingIntent);
    
                var notificationManager = NotificationManager.FromContext(this);
    
                notificationManager.Notify(0, notificationBuilder.Build());
            }
            else
            {
                var intent = new Intent(this, typeof(MainActivity));
                intent.AddFlags(ActivityFlags.ClearTop);
                var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.OneShot);
    
                var notificationBuilder = new Android.App.Notification.Builder(this, Utils.CHANNEL_ID)
                            .SetContentTitle(Header)
                            .SetSmallIcon(Resource.Drawable.icon)
                            .SetContentText(body)
                            .SetAutoCancel(true)
                            .SetContentIntent(pendingIntent)
                            .SetChannelId(Utils.CHANNEL_ID);
    
                if (Build.VERSION.SdkInt < BuildVersionCodes.O)
                {
                    return;
                }
    
                var channel = new NotificationChannel(Utils.CHANNEL_ID, "FCM Notifications", NotificationImportance.High)
                {
                    Description = "Firebase Cloud Messages appear in this channel"
                };
    
                var notificationManager = (NotificationManager)GetSystemService(NotificationService);
                notificationManager.CreateNotificationChannel(channel);
    
                notificationManager.Notify(0, notificationBuilder.Build());
            }
        }
    
  • LandLuLandLu Xamurai Member, Xamarin Team Xamurai

    Glad you finally solved it!

  • MarthinchMarthinch ✭✭ Member ✭✭

    Have you implemented this way into xamarin form iOS ?

  • DevanathanDevanathan ✭✭ Member ✭✭

    @Sreeee

    When my app is launched by clicking the notification, always my Intent.Extras is null. Help me to solve this.

  • SreeeeSreeee ✭✭✭✭✭ INMember ✭✭✭✭✭

    @Devanathan I think you need to do that in notification payload .

    Sample notification payload that I am using in my project added below:

    {
     "to" : "fcm_token here",
     "collapse_key" : "type_a",
     "notification" : {
          "body" : "Body of notif",
         "title": "title of notif",
         "priority":"high",
         "content_available":true
     },
     "data" : {
        "ModelData": [
            {
            }
            ]
     },
      "ttl": 3600
    } 
    
Sign In or Register to comment.