Skip to content

Instantly share code, notes, and snippets.

@svedmark
Last active May 19, 2025 17:53
Show Gist options
  • Save svedmark/e71d319590340a75374c3b9b62c564d9 to your computer and use it in GitHub Desktop.
Save svedmark/e71d319590340a75374c3b9b62c564d9 to your computer and use it in GitHub Desktop.
Minimal FCM Push Messaging for .NET MAUI (RC3)
* Setup Firebase project like normal and add google-services.json (make sure Build action is set to GoogleServicesJson)
* Nugets required for MAUI project file: (later versions don't work)
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0-android'">
<PackageReference Include="Xamarin.Firebase.Iid" Version="121.1.0" />
<PackageReference Include="Xamarin.Firebase.Messaging" Version="122.0.0" />
<PackageReference Include="Xamarin.Google.Dagger" Version="2.39.1" />
<PackageReference Include="Xamarin.GooglePlayServices.Base" Version="117.6.0.5" />
</ItemGroup>
* Also add the receiver configuration to the app manifest's application node:
<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>
using Android.App;
using Android.Content;
using AndroidX.Core.App;
using Firebase.Messaging;
namespace FCMApp.Android;
[Service(Exported = false)]
[IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
public class FCMService : FirebaseMessagingService
{
public override void OnMessageReceived(RemoteMessage message)
{
RemoteMessage.Notification notification = message.GetNotification();
IDictionary<string, string> data = message.Data;
string body = "";
string title = "";
if (data != null && data.ContainsKey("body") && data.ContainsKey("title"))
{
body = data["body"];
title = data["title"];
}
else if (notification != null)
{
body = message.GetNotification().Body;
title = message.GetNotification().Title;
}
if (!string.IsNullOrEmpty(body) && !string.IsNullOrEmpty(title))
{
// TODO: Manage this message (we get here only when app is in foreground)
}
}
}
namespace FCMApp;
public interface IMessagingService
{
string GetToken();
bool IsMessagingAvailable();
void SetNewTokenCallback(Action<string> token_callback);
}
using Android.App;
using Android.Content.PM;
using Android.OS;
using Android.Util;
namespace FCMApp;
[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
public class MainActivity : MauiAppCompatActivity
{
static readonly string TAG = "MainActivity";
public static readonly string CHANNEL_ID = "main_channel";
public static readonly int NOTIFICATION_ID = 100;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// handle incoming intent extras (when clicking on a push notification)
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);
}
}
CreateNotificationChannel();
}
void CreateNotificationChannel()
{
// notification channel mandatory only from API 26
if (Build.VERSION.SdkInt < BuildVersionCodes.O)
return;
NotificationManager mgr = (NotificationManager)GetSystemService(NotificationService);
mgr.CreateNotificationChannel(
new NotificationChannel(CHANNEL_ID, "FCM Notifications", NotificationImportance.Default)
{
Description = "Firebase Cloud Messages appear in this channel"
});
}
}
using Android.Gms.Common;
using Android.Gms.Tasks;
using Firebase.Iid;
namespace FCMApp;
public partial class MessagingService
{
public partial bool IsMessagingAvailable() => GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(Android.App.Application.Context) == ConnectionResult.Success;
public partial string GetToken() => FirebaseInstanceId.Instance.Token;
public partial void SetNewTokenCallback(Action<string> token_callback)
{
if (token_callback == null)
throw new InvalidOperationException("Callback cannot be null");
if (GetToken() != null)
token_callback(GetToken());
else
FirebaseInstanceId.Instance.GetInstanceId().AddOnSuccessListener(new OnTokenListener((token) => token_callback(token)));
}
}
public class OnTokenListener : Java.Lang.Object, IOnSuccessListener
{
Action<string> _callback;
public OnTokenListener(Action<string> success_callback) => _callback = success_callback;
public void OnSuccess(Java.Lang.Object result) => _callback?.Invoke(FirebaseInstanceId.Instance.Token);
}
namespace FCMApp;
public partial class MessagingService : IMessagingService
{
public partial string GetToken();
public partial bool IsMessagingAvailable();
public partial void SetNewTokenCallback(Action<string> token_callback);
}
@autoprog
Copy link

hi,
[SOLVED]
public partial bool IsMessagingAvailable() => GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable( Microsoft.Maui.ApplicationModel.Platform.CurrentActivity) == ConnectionResult.Success;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment