4

For Xamarin.Android, when the closed app receives a notification, it triggers HandleIntent(). I want to specify the target (intent) page after opening a background notification, like when receiving a foreground notification when the app is already open.

How do you specify in the HandleIntent() the intent page to deeplink to a different part of the app, instead of the background notification opening to the app homepage? Or is there a way to OnResume() the app and capture the Message.Data values then deeplink to another page?

using System;
using Android.App;
using Android.Content;
using Android.Media;

using Android.Support.V4.App;
using Firebase.Messaging;

namespace Appname
{
    [Service(Name = "com.mydomainname.appname.MyFirebaseMessagingService")]
    [IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
    public class MyFirebaseMessagingService : FirebaseMessagingService
    {
        const string TAG = "MyFirebaseMsgService";
        internal static readonly string CHANNEL_ID = "alerts_channel";

        public override void OnNewToken(string token)
        {
            base.OnNewToken(token);
        }

        public override void OnMessageReceived(RemoteMessage message)
        {
            if (message.Data.Count > 0)
            {
                // NOTIFICTION AS DATA WITH ID
                Android.Util.Log.Debug(TAG, "From: " + message.From);
                Android.Util.Log.Debug(TAG, "Title: " + message.GetNotification().Title);
                Android.Util.Log.Debug(TAG, "Notification Message Body: " + message.GetNotification().Body);
                Android.Util.Log.Debug(TAG, "Data: " + message.Data["EId"]);
                SendNotification(message.GetNotification().Title, message.GetNotification().Body, message.Data["EId"]);
            }
            else
            {
                // NOTIFICATION WITHOUT DATA
                Android.Util.Log.Debug(TAG, "From: " + message.From);
                Android.Util.Log.Debug(TAG, "Title: " + message.GetNotification().Title);
                Android.Util.Log.Debug(TAG, "Notification Message Body: " + message.GetNotification().Body);
                SendNotification(message.GetNotification().Title, message.GetNotification().Body, null);
            }
        }

        public override void HandleIntent(Intent intent)// this method will fire when the app in background/closed state, and the foreground before calling OnMessageReceived()
        {
            base.HandleIntent(intent);
            string strTitle = "";
            string strBody = "";
            string strEId = "";

            if (intent.Extras != null)
            {
                foreach (var key in intent.Extras.KeySet())
                {
                    var value = intent.Extras.GetString(key);
                    switch (key)
                    {
                        case "gcm.notification.title":
                            strTitle = value;
                            break;
                        case "gcm.notification.body":
                            strBody = value;
                            break;
                        case "EId":
                            strEId = value;
                            break;
                    }
                }
            }
        }

        void SendNotification(string messageTitle, string messageBody, string strEId)
        {
            Intent intent;
            if(strEId == null)
            {
                intent = new Intent(this, typeof(MainActivity));
            }
            else
            {
                intent = new Intent(this, typeof(pageEvent));
                intent.PutExtra("EID", strEId);
            }

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

            var defaultSoundUri = RingtoneManager.GetDefaultUri(RingtoneType.Notification);
            var notificationBuilder = new NotificationCompat.Builder(this, CHANNEL_ID)
                .SetSmallIcon(Resource.Mipmap.ic_launcher_round)
                .SetContentTitle(messageTitle)
                .SetContentText(messageBody)
                .SetAutoCancel(true)
                .SetSound(defaultSoundUri)
                .SetContentIntent(pendingIntent);

            var notificationManager = NotificationManager.FromContext(this);

            notificationManager.Notify(0 /* ID of notification */, notificationBuilder.Build());
        }
    }
}
detailCode
  • 537
  • 1
  • 8
  • 22
  • I'm not very familiar with the details of this, but two (vague) ideas come to mind: 1) In HandleIntent, is there some "internal" notification OR MessageCenter message you could fire, that would then be received by the app? 2) If you set some "static" value somewhere, will the app see it when it does OnResume? Bottom line: find *some* way to communication information, that the app can use in OnResume, or shortly after OnResume. (The tricky part is finding a mechanism that does something that isn't wiped out/re-initialized before onResume happens.) – ToolmakerSteve May 14 '21 at 20:46
  • Following this response / example should lead you to what you are trying to do https://stackoverflow.com/questions/25787908/android-how-to-open-a-push-notification-deep-link-intent-that-when-closed-re – Davmi José Valdez Ogando May 16 '21 at 18:45

1 Answers1

0

In the sendNotification function if you look at the intent creation below as per your code you will see name of the activity which is to be opened is specified.

    if(strEId == null)
    {
        intent = new Intent(this, typeof(MainActivity));
    }
    else
    {
        intent = new Intent(this, typeof(pageEvent));
        intent.PutExtra("EID", strEId);
    }

when strEId == null then home screen is opened ie. MainActivity else the page which is specified to open is opened. i.e pageEvent (it can be any activity which you desire).

So what you need to do is specify the activity which you need to open into the intent when certain notification arrives.

Here you have multiple options to choose from on how to deep link to your required screen.

  1. You can just specify the activity in the existing code in the place of pageEvent or create a new intent based on any other condition etc.

intent = new Intent(this, typeof(pageEvent));, ,where pageEvent can be any activity name

  1. You could send a notification type along with the notification data. Then based on the notification type you can specify the kind of activity you need to open along with the data you need to pass to that activity if any.

      void SendNotification(string messageTitle, string messageBody, string strEId,string notifType)
                 {
    
       Intent intent;
    
       switch (notifType) 
       {
         case "home":
           //create intent for home page
           break;
         case "customPage":
           //create intent for customPage
           break;    
     }
    
     now pass the intent to pendingIntent and show the notification.
    

    }

  2. You could go to you home screen from notification while passing the notification type to the home screen intent. Then making a custom function within the homescreen to handle the notification. It will check if there is any notification type from the intent and if it is there then we redirect to the destination screen from the home screen.

thebadassdev
  • 156
  • 9