Skip to content

Instantly share code, notes, and snippets.

@svedmark
Last active March 16, 2024 20:44
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);
}
@mrnams
Copy link

mrnams commented Mar 16, 2024

Thanks for sharing, however methods are not hitting, could you please share working example code?

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