Redirect to Specific Page When Firebase Notification tapped

Hello,

I have implemented android firebase remote notification based on the following walkthrough in my xamarin forms app.

https://docs.microsoft.com/en-us/xamarin/android/data-cloud/google-messaging/remote-notifications-with-fcm?tabs=windows

Now, I would like to redirect to a specific page when the user tapped on the notification badge. Currently, I can able to successfully redirect to a specific page when the app is opened and in an idle state by overriding OnNewIntent method. But when the app is closed it's not redirecting to a specific page when I am tapping on the notification.

FOLLOWING CODE I HAVE USED IN MY APP

MainActivity.cs

public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
static readonly string TAG = "MainActivity";

    internal static readonly string CHANNEL_ID = "my_notification_channel";
    internal static readonly int NOTIFICATION_ID = 100;
    protected override void OnCreate(Bundle savedInstanceState)
    {
        TabLayoutResource = Resource.Layout.Tabbar;
        ToolbarResource = Resource.Layout.Toolbar;

        base.OnCreate(savedInstanceState);
        global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
        //LoadApplication(new App(true));


        string parameterValue = Intent.GetStringExtra("messageBody");
        LoadApplication(parameterValue != null ? new App(true) : new App(false));

        //if (Intent.Extras != null)
        //{
        //    foreach (var key in Intent.Extras.KeySet())
        //    {
        //        var value = Intent.Extras.GetString(key);
        //        //Log.Debug(TAG, "Key: {0} Value: {1}", key, value);
        //        LoadApplication(new App(true));
        //    }
        //}
        //else
        //{
        //    LoadApplication(new App(false));
        //}


        IsPlayServicesAvailable();
        CreateNotificationChannel();
    }

    public bool IsPlayServicesAvailable()
    {
        int resultCode = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(this);
        if (resultCode != ConnectionResult.Success)
        {

            if (GoogleApiAvailability.Instance.IsUserResolvableError(resultCode))
            {
                //msgText.Text = GoogleApiAvailability.Instance.GetErrorString(resultCode);
            }
            else
            {
                // msgText.Text = "This device is not supported";
                Finish();
            }
            return false;
        }
        else
        {
            // do whatever if play service is not available
            //msgText.Text = "Google Play Services is available.";
            return true;
        }
    }

    void CreateNotificationChannel()
    {
        if (Build.VERSION.SdkInt < BuildVersionCodes.O)
        {
            return;
        }

        var channel = new NotificationChannel(CHANNEL_ID,
                                              "FCM Notifications",
                                              NotificationImportance.Default)
        {

            Description = "Firebase Cloud Messages appear in this channel"
        };

        var notificationManager = (NotificationManager)GetSystemService(Android.Content.Context.NotificationService);
        notificationManager.CreateNotificationChannel(channel);
    }

    protected override void OnNewIntent(Intent intent)
    {
        //var message = intent.GetStringExtra("message");
        base.OnNewIntent(intent);
        Intent = intent;
        Xamarin.Forms.Application.Current.MainPage.Navigation.PushAsync(new Views.AboutPage());

    }
}

MyFirebaseMessagingService.cs

[Service]
[IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
public class MyFirebaseMessagingService : FirebaseMessagingService
{
public MyFirebaseMessagingService()
{

    }
    public override void OnMessageReceived(RemoteMessage message)
    {
        //base.OnMessageReceived(message);
        //webContentList = message.Data["webContentList"];
        //new NotificationHelper().CreateNotification(message.GetNotification().Title, message.GetNotification().Body);
        var body = message.GetNotification().Body;
        SendNotification(body, message.Data);
    }

    void SendNotification(string messageBody, IDictionary<string, string> data)
    {
        var intent = new Intent(this, typeof(MainActivity));
        intent.AddFlags(ActivityFlags.ClearTop);
        foreach (var key in data.Keys)
        {
            intent.PutExtra(key, data[key]);
        }
        intent.PutExtra("messageBody", messageBody.ToString());

        var pendingIntent = PendingIntent.GetActivity(this,
                                                      MainActivity.NOTIFICATION_ID,
                                                      intent,
                                                      PendingIntentFlags.OneShot);

        var notificationBuilder = new NotificationCompat.Builder(this, MainActivity.CHANNEL_ID)
                                  .SetSmallIcon(Resource.Drawable.icon)
                                  .SetContentTitle("FCM Message")
                                  .SetContentText(messageBody)
                                  .SetAutoCancel(true)
                                  .SetContentIntent(pendingIntent);

        var notificationManager = NotificationManagerCompat.From(this);
        notificationManager.Notify(MainActivity.NOTIFICATION_ID, notificationBuilder.Build());
    }
}

App.xaml.cs

public App(bool hasNotification)
{
InitializeComponent();

//testing the feature
if (hasNotification)
{
MainPage = new NavigationPage(new HomePage());
}
else
{
MainPage = new MainPage();
}
}

Any help would be highly appreciated.

Thanks
Ranjan

Answers

  • LandLuLandLu Member, Xamarin Team Xamurai

    When the app is closed the OnMessageReceived won't be triggered so the custom notification won't be displayed. This is why OnNewIntent won't be called.
    We need to create a new activity with a filter like:

    [Activity(Label = "SecondActivity")]
    [IntentFilter(new[] { ".Activities.SecondActivity" }, Categories = new[] { "android.intent.category.DEFAULT" })]
    public class SecondActivity : Activity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
    
            // Create your application here
            SetContentView(Resource.Layout.activity_second);
        }
    }
    

    Then this activity will be opened if your payload is:

    "notification": {
        "title": "hello",
        "body": "yo",
        "click_action": ".Activities.SecondActivity" // for intent filter in your activity
    },
    

    The system will handle the notification tray if your application is closed and opened the activity depending on the click_action. At last, we could add extra configuration in this activity. i.e. navigate back to MainActivity and push a new page in Forms. Do not forget if you want to display forms page we have to go back to MainActivity as all the pages are controlled by it.

Sign In or Register to comment.