I've seen many different types of solutions which may have worked in the past, but nothing solid that has worked for myself. And it's a minefield of what people say works, what doesn't work, what has changed, etc. But I'm trying to find not only a solution but hopefully an understanding - because right now I am seriously confused.
What I can do right now - My Xamarin Forms app (Android) can receive push notification if the app is in the Foreground/Background, I can also intercept these notifications when the user taps them so I can tell my app what to do.
What I am trying to do - Essentially the above but in the state of where the app has been completely stopped.
I have my Firebase Messaging setup which is wired to Azure Notification Hub - unfortunately, I won't be moving away from Azure (just in case anyone suggests to drop it). Most of what I have currently is information I've managed to stitch together from various Microsoft Documentation (here I don't use AppCenter - just used this to cross-reference any useful code, here, here, and here ), other StackOverflow questions (such as here, here, and here - far too many more to link) and the Xamarin forum - so again, apologies if there is any obsolete code being used (please let me know - I have tried my best to use up-to-date methods, etc).
The type of push notifications that I am sending are Data Messages which I read up on here, I'm using custom data in my notifications therefore it is my understanding this is the correct type of push I want to send, as shown below.
{
    "data": {
        "title": "Title Test",
        "body": "Push notification body test",
        "area": "SelectedPage"
    }
}
Below is the current code I have setup in my project to handle push notifications thus far.
Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.pushtesting" android:installLocation="auto">
    <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" />
    <application android:label="Push Testing">
        <receiver android:name="com.google.firebase.iid.FirebaseInstanceIdInternalReceiver" android:exported="false" />
        <receiver android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver" android:exported="true" android:permission="com.google.android.c2dm.permission.SEND">
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
                <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
                <category android:name="${applicationId}" />
            </intent-filter>
        </receiver>
    </application>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>
MainActivity.cs
I have LaunchMode = LaunchMode.SingleTop, would my understanding be correct, for this is to ensure the current Activity is still used instead of creating a new one - for instance, when the user would tap a notification - implementing it plus additional code (below) seems to suggest this is true.
protected override void OnNewIntent(Intent intent) {
    base.OnNewIntent(intent);
    String area = String.Empty;
    String extraInfo = String.Empty;
    if (intent.Extras != null) {
        foreach (String key in intent.Extras.KeySet()) {
            String value = intent.Extras.GetString(key);
            if (key == "Area" && !String.IsNullOrEmpty(value)) {
                area = value;
            } else if (key == "ExtraInfo" && !String.IsNullOrEmpty(value)) {
                extraInfo = value;
            }
        }
    }
    NavigationExtension.HandlePushNotificationNavigation(area, extraInfo);
}
Using OnNewIntent to intercept the push notification when the user interacts with it.
MyFirebaseMessaging.cs
using System;
using System.Threading.Tasks;
using Android.App;
using Android.Content;
using Android.Support.V4.App;
using Android.Util;
using Firebase.Messaging;
using PushTesting.Models;
using WindowsAzure.Messaging;
namespace PushTesting.Droid.Services {
    [Service]
    [IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
    public class OcsFirebaseMessaging : FirebaseMessagingService {
        private const String NotificationChannelId = "1152";
        private const String NotificationChannelName = "Push Notifications";
        private const String NotificationChannelDescription = "Receive notifications";
        private NotificationManager notificationManager;
        public override void OnNewToken(String token) => SendTokenToAzure(token);
        /// <summary>
        /// Sends the token to Azure for registration against the device
        /// </summary>
        private void SendTokenToAzure(String token) {
            try {
                NotificationHub hub = new NotificationHub(Constants.AzureConstants.NotificationHub, Constants.AzureConstants.ListenConnectionString, Android.App.Application.Context);
                Task.Run(() => hub.Register(token, new String[] { }));
            } catch (Exception ex) {
                Log.Error("ERROR", $"Error registering device: {ex.Message}");
            }
        }
        /// <summary>
        /// When the app receives a notification, this method is called
        /// </summary>
        public override void OnMessageReceived(RemoteMessage remoteMessage) {
            Boolean hasTitle = remoteMessage.Data.TryGetValue("title", out String title);
            Boolean hasBody = remoteMessage.Data.TryGetValue("body", out String body);
            Boolean hasArea = remoteMessage.Data.TryGetValue("area", out String area);
            Boolean hasExtraInfo = remoteMessage.Data.TryGetValue("extraInfo", out String extraInfo);
            PushNotificationModel push = new PushNotificationModel {
                Title = hasTitle ? title : String.Empty,
                Body = hasBody ? body : String.Empty,
                Area = hasArea ? area : String.Empty,
                ExtraInfo = hasExtraInfo ? extraInfo : String.Empty
            };
            SendNotification(push);
        }
        /// <summary>
        /// Handles the notification to ensure the Notification manager is updated to alert the user
        /// </summary>
        private void SendNotification(PushNotificationModel push) {
            // Create relevant non-repeatable Id to allow multiple notifications to be displayed in the Notification Manager
            Int32 notificationId = Int32.Parse(DateTime.Now.ToString("MMddHHmmsss"));
            Intent intent = new Intent(this, typeof(MainActivity));
            intent.AddFlags(ActivityFlags.ClearTop | ActivityFlags.SingleTop);
            intent.PutExtra("Area", push.Area);
            intent.PutExtra("ExtraInfo", push.ExtraInfo);
            PendingIntent pendingIntent = PendingIntent.GetActivity(this, notificationId, intent, PendingIntentFlags.UpdateCurrent);
            notificationManager = (NotificationManager)GetSystemService(Context.NotificationService);
            // Creates Notification Channel for Android devices running Oreo (8.0.0) or later
            if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O) {
                NotificationChannel notificationChannel = new NotificationChannel(NotificationChannelId, NotificationChannelName, NotificationImportance.High) {
                    Description = NotificationChannelDescription
                };
                notificationManager.CreateNotificationChannel(notificationChannel);
            }
            // Builds notification for Notification Manager
            Notification notification = new NotificationCompat.Builder(this, NotificationChannelId)
            .SetSmallIcon(Resource.Drawable.ic_launcher)
            .SetContentTitle(push.Title)
            .SetContentText(push.Body)
            .SetContentIntent(pendingIntent)
            .SetAutoCancel(true)
            .SetShowWhen(false)
            .Build();
            notificationManager.Notify(notificationId, notification);
        }
    }
}
Then finally my Firebase class where I use OnNewToken() to register to Azure with, OnMessageReceived() is overridden so I can handle a push notification being received and then SendNotification() which is being used to build and show the notification.
Any and all help will be highly appreciated!
 
    