Creating push notifications for Android in .NET MAUI

Serhii Korol - Jul 5 '23 - - Dev Community

Hello colleagues. In this article, I want to introduce you to Firebase notification implementation. It's a super easy realization and I show how.

Creating Firebase project

Go to the https://console.firebase.google.com and click on the huge + and begin creating a project.

1 step

Let's name the project "push-maui". Click "Continue".
In the second step leave it unchanged.

2 step

In the last step select an account and click "Create project".

3 step

After one minute - click "Continue".

finish

Creating MAUI project

Let's create a new project:

dotnet new maui -n PushMauiSample
cd PushMauiSample
Enter fullscreen mode Exit fullscreen mode

Open the solution in your favorite IDE. Before we begin implementing Firebase Cloud Messaging, let's add Plugin.Firebase package. I install an older version since it is compatible with JDK. The newest version has issues:

dotnet add package Plugin.Firebase 1.2.0
Enter fullscreen mode Exit fullscreen mode

And also, for Android you need these packages:

dotnet add package Xamarin.Kotlin.StdLib.Jdk7
dotnet add package Xamarin.Kotlin.StdLib.Jdk8
Enter fullscreen mode Exit fullscreen mode

Further, go to the PushMauiSample.proj, delete all non-android settings, and inject Google services. It should be something like that:

<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <TargetFramework>net7.0-android</TargetFramework>

        <OutputType>Exe</OutputType>
        <RootNamespace>PushMauiSample</RootNamespace>
        <UseMaui>true</UseMaui>
        <SingleProject>true</SingleProject>
        <ImplicitUsings>enable</ImplicitUsings>

        <!-- Display name -->
        <ApplicationTitle>PushMauiSample</ApplicationTitle>

        <!-- App Identifier -->
        <ApplicationId>com.companyname.pushmauisample</ApplicationId>
        <ApplicationIdGuid>d0db7add-d444-449e-bb11-c0ff3569174c</ApplicationIdGuid>

        <!-- Versions -->
        <ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
        <ApplicationVersion>1</ApplicationVersion>

        <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">21.0</SupportedOSPlatformVersion>
    </PropertyGroup>

    <ItemGroup>
        <!-- App Icon -->
        <MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\appiconfg.svg" Color="#512BD4" />

        <!-- Splash Screen -->
        <MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#512BD4" BaseSize="128,128" />

        <!-- Images -->
        <MauiImage Include="Resources\Images\*" />
        <MauiImage Update="Resources\Images\dotnet_bot.svg" BaseSize="168,208" />

        <!-- Custom Fonts -->
        <MauiFont Include="Resources\Fonts\*" />

        <!-- Raw Assets (also remove the "Resources\Raw" prefix) -->
        <MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
    </ItemGroup>

    <ItemGroup Condition="'$(TargetFramework)' == 'net7.0-android'">
        <GoogleServicesJson Include="google-services.json" />
    </ItemGroup>

    <ItemGroup>
        <PackageReference Include="Plugin.Firebase" Version="1.2.0" />
    </ItemGroup>

    <ItemGroup Condition="'$(TargetFramework)' == 'net7.0-android'">
      <PackageReference Include="Xamarin.Kotlin.StdLib.Jdk7" Version="1.8.22" />
      <PackageReference Include="Xamarin.Kotlin.StdLib.Jdk8" Version="1.8.22" />
    </ItemGroup>

    <ItemGroup>
      <MauiPlatformSpecificFolder Remove="Platforms\iOS\" />
      <MauiPlatformSpecificFolder Remove="Platforms\MacCatalyst\" />
      <MauiPlatformSpecificFolder Remove="Platforms\Tizen\" />
      <MauiPlatformSpecificFolder Remove="Platforms\Windows\" />
    </ItemGroup>

</Project>

Enter fullscreen mode Exit fullscreen mode

After that, you did it. Let's register the service. Add this code to MauiProgram.cs:

private static MauiAppBuilder RegisterFirebaseServices(this MauiAppBuilder builder)
    {
        builder.ConfigureLifecycleEvents(events =>
        {

            events.AddAndroid(android => android.OnCreate((activity, state) =>
                CrossFirebase.Initialize(activity, CreateCrossFirebaseSettings())));
        });

        builder.Services.AddSingleton(_ => CrossFirebaseAuth.Current);
        return builder;
    }

    private static CrossFirebaseSettings CreateCrossFirebaseSettings()
    {
        return new CrossFirebaseSettings(isAuthEnabled: true, isCloudMessagingEnabled: true);
    }
Enter fullscreen mode Exit fullscreen mode

And sure, you should update this method:

public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .RegisterFirebaseServices()
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
            });

        return builder.Build();
    }
Enter fullscreen mode Exit fullscreen mode

Registering an application

And now, let's return to Firebase Console and register the application. You should choose Android.

select app

There are four steps. The more important is first. The Android package name is project id. Let's name it dev.to.android.push. Click the Register app.
In the next step, save google-services.json to the root of your project. Click Next.

save servvices

The next steps without changes. In the end, click "Continue to console".

A few settings and implementation

Let's return to PushMauiSample.proj and find this row:

<ApplicationId>com.companyname.pushmauisample</ApplicationId>
Enter fullscreen mode Exit fullscreen mode

You should replace to dev.to.android.push name that we registered in the Firebase console. The same name you can find in google-services.json file. This name should identical.
Next, go to the MainPage.xaml and paste this code in VerticalStackLayout block:

<Image
                HeightRequest="200"
                HorizontalOptions="Center"
                SemanticProperties.Description="Cute dot net bot waving hi to you!"
                Source="dotnet_bot.png" />

            <Label
                FontSize="32"
                HorizontalOptions="Center"
                SemanticProperties.HeadingLevel="Level1"
                Text="Hello, Firebase notifications" />

            <Label
                FontSize="18"
                HorizontalOptions="Center"
                SemanticProperties.Description="Welcome to dot net Multi platform App U I"
                SemanticProperties.HeadingLevel="Level2"
                Text="Welcome to .NET Multi-platform App UI" />

            <Button
                Clicked="GetTokenClicked"
                HorizontalOptions="Center"
                SemanticProperties.Hint="Get registration id token"
                Text="Get Token"
                x:Name="CounterBtn" />
Enter fullscreen mode Exit fullscreen mode

After that, you should create an event handler like this:

private async void GetTokenClicked(object sender, EventArgs e)
    {
        await CrossFirebaseCloudMessaging.Current.CheckIfValidAsync();
        var token = await CrossFirebaseCloudMessaging.Current.GetTokenAsync();
        Token = token;
        await DisplayAlert("FCM token", token, "OK");
    }
Enter fullscreen mode Exit fullscreen mode

And don't forget to add a property for keeping token:

public string Token { get; set; }
Enter fullscreen mode Exit fullscreen mode

The first part is ready. Let's check out it.

main page

got token

We got a token that was registered in Firebase. Without this token, you can't send notifications.

Implementing sending notifications

And now, we need to configure sending notifications.
Let's return to the Firebase console again and find gears. Select the "Project settings" and "Service accounts" tab. Click "Generate new private key."

settings

Save it to your project into Resources/Raw folder with name firebase-adminsdk.json.

After that return to MainPage.xaml and add the button:

<Button
                Clicked="SendPushClicked"
                HorizontalOptions="Center"
                SemanticProperties.Hint="Send notification"
                Text="Send push"
                x:Name="SendPush" />
Enter fullscreen mode Exit fullscreen mode

Add handler to MainPage.cs. Here it loads the file sdk settings and creates an application that sends a notification:

private async void SendPushClicked(object sender, EventArgs e)
    {
        var app = FirebaseApp.Create(new AppOptions
        {
            Credential = await GetCredential()
        });

        FirebaseMessaging messaging = FirebaseMessaging.GetMessaging(app);
        var message = new Message()
        {
            Token = Token,
            Notification = new Notification { Title = "Hello world!", Body = "It's a message for Android with MAUI"},
            Data = new Dictionary<string, string> {{"greating", "hello"}},
            Android = new AndroidConfig { Priority = Priority.Normal},
            Apns = new ApnsConfig { Headers = new Dictionary<string, string> { {"apns-priority", "5"}}}
        };
        var response = await messaging.SendAsync(message);
        await DisplayAlert("Response", response, "OK");
    }

    private async Task<GoogleCredential> GetCredential()
    {
        var path = await FileSystem.OpenAppPackageFileAsync("firebase-adminsdk.json");
        return GoogleCredential.FromStream(path);
    }
Enter fullscreen mode Exit fullscreen mode

You'll see a lot of unresolved code, it means you need the FirbaseAdminCore package:

dotnet add package FirbaseAdminCore
Enter fullscreen mode Exit fullscreen mode

After installing your code will resolved. And naw became time check out our application.

main

Getting token:

token

Sending push:

send

Finally, we got the notification:

push

Conclusion.

It's an easy way to make notifications for mobile devices. Put likes on and subscribe. Happy coding!

Source code here.

Buy Me A Beer

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .