Xamarin Forms: Implement push notification tapping on android platform

Sreejith Sreenivasan 896 Reputation points
2023-06-07T14:54:25.0666667+00:00

I have implemented push notification on my Xamarin forms application using FCM.

My code

	[Service(Enabled = true, Exported = true)]
	[IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
	public class FirebaseNotificationService : FirebaseMessagingService
	{
		public override void OnNewToken(string token)
		{
			base.OnNewToken(token);
			SendRegistrationTokenToMainPRoject(token);
		}

		public static string requestData = "";
		public static string messageType = "";
		public static string revealedLocationName = "";
		public static string revealedLocationId = "";
		public override void OnMessageReceived(RemoteMessage message)
		{
			base.OnMessageReceived(message);

			var Body = message.GetNotification().Body;
			var title = message.GetNotification().Title;
			var id = message.MessageId;

			string notifId = message.MessageId;
			string b = string.Empty;
			for (int i = 0; i < notifId.Length; i++)
			{
				if (Char.IsDigit(notifId[i]))
					b += notifId[i];
			}

			requestData = message.Data["requestData"];
			messageType = message.Data["commentMessageType"];
			revealedLocationName = message.Data["revealedLocationName"];
			revealedLocationId = message.Data["revealedLocationId"];
			Console.WriteLine("requestData:>>" + requestData);
			var myData = JsonConvert.DeserializeObject<RequestList>(requestData);
			Console.WriteLine("myData:>>" + myData);
			MessagingCenter.Send<object, string>(this, "requestData", requestData);

			string requestId = myData.request.itemId;
			MessagingCenter.Send<object, string>(this, "requestId_from_notification", requestId);

			try
			{
				string body = System.Net.WebUtility.UrlDecode(message.GetNotification().Body.ToString());
				string header = System.Net.WebUtility.UrlDecode(message.GetNotification().Title.ToString());
				SendNotificatios(body, header);
			}
			catch (Exception ex)
			{
				Console.WriteLine("Error:>>" + ex);
			}
		}

		public void SendNotificatios(string body, string Header)
		{
			var intent = new Intent(this, typeof(MainActivity));
			intent.AddFlags(ActivityFlags.ClearTop);
			var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.Mutable);

			if (Build.VERSION.SdkInt < BuildVersionCodes.O)
			{
				var notificationBuilder = new NotificationCompat.Builder(this)
							.SetContentTitle(Header)
							.SetContentText(body)
							.SetSmallIcon(Resource.Mipmap.ic_notification)
							.SetAutoCancel(true)
							.SetContentIntent(pendingIntent);

				var notificationManager = GetSystemService(Context.NotificationService) as NotificationManager;
				notificationManager.Notify(new Random().Next(), notificationBuilder.Build());
			}
			else
			{
				var notificationBuilder = new NotificationCompat.Builder(this, Utils.CHANNEL_ID)
							.SetContentTitle(Header)
							.SetContentText(body)
							.SetSmallIcon(Resource.Mipmap.ic_notification)
							.SetAutoCancel(true)
							.SetContentIntent(pendingIntent);

				var notificationManager = GetSystemService(Context.NotificationService) as NotificationManager;

				NotificationChannel channel = new NotificationChannel(Utils.CHANNEL_ID, "FCM Notifications", NotificationImportance.Default);
				notificationManager.CreateNotificationChannel(channel);
				notificationManager.Notify(new Random().Next(), notificationBuilder.Build());
			}
		}

		void SendRegistrationTokenToMainPRoject(string token)
		{
			try
			{
				//Save token Locally Here
				MessagingCenter.Send<object, string>(this, "fcmtoken", token);
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex.Message);
			}
		}
	}

Here I am using notifications for the messages. So when I tap on any notification I read the data from notification and pass it to App.xaml. From there I open my message page.

Notification Tapping:

	//Background or killed mode
	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);
			if (key == "requestData") // Make it Dynamic instead of hardcoding here 
			{
				if (value?.Length > 0)
				{
					isNotification = true;
					LoadApplication(new App(value, FirebaseNotificationService.messageType, FirebaseNotificationService.revealedLocationName, FirebaseNotificationService.revealedLocationId));
				}
			}
		}
	}
	//Foreground mode
	if (FirebaseNotificationService.requestData.ToString() != "")
	{
		isNotification = true;
		LoadApplication(new App(FirebaseNotificationService.requestData.ToString(), FirebaseNotificationService.messageType, FirebaseNotificationService.revealedLocationName, FirebaseNotificationService.revealedLocationId));
		FirebaseNotificationService.requestData = "";
	}

	//Normal loading
	if (!isNotification)
	{
		LoadApplication(new App(string.Empty, FirebaseNotificationService.messageType,FirebaseNotificationService.revealedLocationName, FirebaseNotificationService.revealedLocationId));
	}

My Notification data:

	{
	"to" : "device-fcm-token",
	"notification" : {
		"body" : "Hiii",
		"title": "Title"
	},
	"data" : {
		"commentMessageType": "customer",
		"revealedLocationName": "Moncy Events Center",
		"revealedLocationId": "77451",
		"requestData":
			{
				"request": {
					"itemId": 3226,
					"itemTitle": "Need car maintanance service",
					"itemDescription": "Need car maintanance service",
					"itemType": "request",
					"itemStatus": 1,
					"itemSource": 0,
					"itemPriority": 1
				},
				"category": "Vehicle Rental",
				"companyId": 0,
				"companyName": null
			}
		}  
	}

My problem is on the notification tapping on Foreground mode, and a minor issue on background or killed mode. On foreground mode, I am reading data in a wrong approach.

LoadApplication(new App(FirebaseNotificationService.requestData.ToString(), FirebaseNotificationService.messageType, FirebaseNotificationService.revealedLocationName, FirebaseNotificationService.revealedLocationId));

Here I have directly taking the requestData, messageType, revealedLocationName, and revealedLocationId variable values using the class FirebaseNotificationService.

So if one notification received, at that time all the above values will set on FirebaseNotificationService variables. And if again a new notification received, the new notification values will set on above variables by replacing the first notification values. So the first notification values will lose and if I tap on it nothing will happen.

So in foreground mode, no matter how many notifications received, my logic will take the last received notifications values. Same mistake I have done on background mode for messageType, revealedLocationName, and revealedLocationId variables.

I need to change this logic and read the exact value of tapped notification and pass it to App.xaml. I have created a ticket on last year for the same issue, unfortunately I can't follow it properly. This is a show stopper issue for me, so please help me to fix this.

Xamarin
Xamarin
A Microsoft open-source app platform for building Android and iOS apps with .NET and C#.
5,357 questions
{count} votes

Accepted answer
  1. Yonglun Liu (Shanghai Wicresoft Co,.Ltd.) 43,371 Reputation points Microsoft Vendor
    2023-06-27T07:36:33.43+00:00

    Hello,

    Notifications in Android are essentially an intent service, so you could use PutExtra to set key/value for notifications.

    In fact, the official example of push notifications in Xamarin.Forms has demonstrated how to save and read custom data to notifications.

    You could refer to the following documentation and code samples.

    In the SendNotification method, you could see that in this instance, there is intent.PutExtra(TitleKey, title); to save title.

    In the CreateNotificationFromIntent method, you could use the string title = intent. GetStringExtra(AndroidNotificationManager.TitleKey); to get the value of title.

    Best Regards,

    Alec Liu.


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.