Xamarin Android: FCM Push notification handling on terminated app: key to the success

If you have ever tried to make an app, that handles a specific type of push notification differently than just simply show a notification to the user, you may have found yourself in trouble. To handle notification receive in a terminated app state, you have to send the payload differently than normal cases.

You should send data only push with high priority to be able to handle the notification by yourself in your app.

The following example shows a perfect payload for Android with FireBase Admin SDK for C#:

			var data = new Dictionary<string, string>();
			data.Add("MessageType", "UrgentNotification");
			data.Add("Title", "Hello Xamarin.Android");
			data.Add("Content", "This notification has been handled by the app");

			FirebaseAdmin.Messaging.Message Message = new FirebaseAdmin.Messaging.Message()
			{
				Token = token,
				Data = data,
				Android = new FirebaseAdmin.Messaging.AndroidConfig()
				{
					Priority = FirebaseAdmin.Messaging.Priority.High,
					Data = data
				}
			};

As you see in the example, the Notification property is completely missing from the payload. But how to handle this notification on the client side? Here’s the solution:

First thing first: Make soure you’re able to receive notifications foreground.
Add google-services.json, make sure the bundlename matches the setting in firebase, etc, etc.

Derive from FirebaseMessagingService

You should make a service, derived from FirebaseMessagingService with an intentfilter to be able to catch Messaging events.

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

OnMessageReceived will be triggered when the application is terminated or it is in foreground. But not even in debug mode. You need to set the build config to release, in order to receive messages when your app is killed by the user. You can display local notification from the data passed as parameter array like this:

if (data?.ContainsKey("UrgentNotification") == true)
			{
				var intent = new Intent(this, typeof(MainActivity));
				intent.AddFlags(ActivityFlags.ClearTop);
				foreach (var key in data.Keys)
				{
					intent.PutExtra(key, data[key]);
				}



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

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

				notificationManager.Notify(MainActivity.NOTIFICATION_ID, notificationBuilder.Build()); 
			}

Or start an activity. (Works only below Android 10):

var startActivityIntent = new Intent(this, typeof(MainActivity));
					startActivityIntent.SetAction("ACTION_VIEW");
					startActivityIntent.SetFlags(ActivityFlags.NewTask);

					StartActivity(startActivityIntent);
This content has 4 years. Some of the information in this post may be out of date or no longer work. Please, read this page keeping its age in your mind.

Xamarin Forms: BoxViews Color get’s lost when updating CornerRadius

In Version 4.8.0.1451 of Xamarin Forms NuGet package, when you update the BoxView’s Corner Radius, the Color property will be cleared.

Issue opened here:
https://github.com/xamarin/Xamarin.Forms/issues/12061

This content has 4 years. Some of the information in this post may be out of date or no longer work. Please, read this page keeping its age in your mind.

Xamarin Forms: Infinite scrolling ListView

To get a dynamic “paged” loading for your list view, follow the steps below:

Make a new usercontrol in your forms project. Derive from ContentView instead from ListView. By deriving from listview, you simply can not Count the items binded to the ItemsSource property, which is the base of the Fetching logic.

public class InfiniteScrollListView : ContentView

Make a countable ItemsSource bindable property for your new usercontrol.

		public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create(
														propertyName: "ItemsSource",
														returnType: typeof(IList),
														declaringType: typeof(View),
														defaultValue: null,
														defaultBindingMode: BindingMode.TwoWay,
														propertyChanged: null);

		public IList ItemsSource
		{
			get { return (IList)GetValue(ItemsSourceProperty); }
			set { SetValue(ItemsSourceProperty, value); }
		}

We need to get the usercontrol to display a listview for us. Make a new instance of a listview. You can specify a caching strategy for the listview, which can be useful on lists have a lot of items. Set the contenview’s content to the new listview instance.

		public InfiniteScrollListView()
		{
			_listViewInstance = new ListView(cachingStrategy: ListViewCachingStrategy.RecycleElement);
			_listViewInstance.HorizontalOptions = LayoutOptions.Fill;
			_listViewInstance.VerticalOptions = LayoutOptions.Fill;
			_listViewInstance.ItemAppearing += InfiniteScrollListView_ItemAppearing;
			_listViewInstance.SetBinding(ListView.ItemsSourceProperty, new Binding(nameof(ItemsSource), BindingMode.TwoWay, source: this));
			Content = _listViewInstance;
		}

		~InfiniteScrollListView()
		{
			if (_listViewInstance != null)
				_listViewInstance.ItemAppearing -= InfiniteScrollListView_ItemAppearing;
		}

The ItemAppearing event is the most important event in our Infinite scrolling listview instance. It’s called, when an item is displayed “phisically” on the screen. Let’s make an eventhandler for it. We are using a new Bindable Property for fetching data command, which will be called, when the last item of the ItemsSource has been displayed, and an another Bindable property, to turn off the fetching if the Data access layer could not provide more elements for the query. The _lastElementIndex will be the e.ItemIndex.

if (_lastItemDisplayedIndex == (ItemsSource?.Count - 1 ?? int.MinValue))
			{
				if (HasMoreItems)
				{
					if (FetchDataCommand?.CanExecute(null) == true)
					{
						FetchDataCommand?.Execute(null);
					}
				}
			}

This content has 4 years. Some of the information in this post may be out of date or no longer work. Please, read this page keeping its age in your mind.

Xamarin Android: Dismiss lock screen or show activity on lock screen

To gain an Activity to be showed on the lock screen, or bypass the phone’s lock screen (aka Keyguard) for important notification handling, for example an Incoming VOIP call, you need to do the following:

Set the permission for disabling keyguard. Add the following permission to the AndroidManifest.xml:

  <uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>

Add flags to the Activity’s Window in order to show the activity on the lock screen, or to bypass the lock screen.

this.Window.AddFlags(WindowManagerFlags.DismissKeyguard | WindowManagerFlags.ShowWhenLocked);

Dismiss the keyguard if needed. (CrossCurrentActivity plugin is used to get the current activity):

KeyguardManager keyguardManager = (KeyguardManager)CrossCurrentActivity.Current.Activity?.GetSystemService(Context.KeyguardService);
if (keyguardManager != null)
{	
	keyguardManager.RequestDismissKeyguard(CrossCurrentActivity.Current.Activity, null);
}

This content has 4 years. Some of the information in this post may be out of date or no longer work. Please, read this page keeping its age in your mind.