DEV Community

Cover image for Creating push notifications for Android in .NET MAUI
Serhii Korol
Serhii Korol

Posted on

Creating push notifications for Android in .NET MAUI

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

Top comments (8)

Collapse
 
tommixoft profile image
Tomas

WHAT A FKNG NONSENSE! Really!? Need internet to be able to show some crappy notification to a phone!!? This is the worst aprouch ever created. Also why in the hell you privide maybe sensetive data to 3rd party??? why google or whoever owns firebase, send data? TERRIBLE IDEA!!

Collapse
 
kasp_cf5bcdf0da8b508e30ba profile image
Kasp

You need to grab ASAP a manual because you don't seem to know the difference between local and remote (push notifications) and what are they used for.

In remote notifications you have to send this data to third parties. FCM in case of Android and APS in case of iOS. Those services are in charge of sending the notification to the device or group of devices. So yes, you need internet in this case.

If you just want your application to be able to generate notifications when something happens, you should take a look into local notifications. To generate local notifications you won't need internet connection.

Collapse
 
vlinakis profile image
Vasilis Linakis

Hi Serhii,

Excellent post and work! Thank you very much.
I get everything working right but the Push notification doesn't arrive. I get a warning about the Channel being Null.

Developer warning for package "xxx.xxx.xxx". Failed to post notification on channel "null". See log for more details.

Is there anyway you can help?

Also, have you created an iOS version of your solution?

Thanks again!
Vasilis

Collapse
 
serhii_korol_ab7776c50dba profile image
Serhii Korol

I hadn't created it for iOS since I don't have an Apple Developer account. Likely, iOS requires additional settings. It needs investigating. I recalled why I didn't make it for iOS. I was having issues with packages. For this reason, I refused the idea. The iOS is capricious.

Collapse
 
vlinakis profile image
Vasilis Linakis

Thanks for your immediate reply.
How about the issue with the channel? Have you managed to reproduce it and maybe solve it?

Collapse
 
clauselmann profile image
ClausElmann

Hi Serhii

Just pulled you repo and replaced google-services.json and firebase-adminsdk.json
and ran dotnet restore

But I then get this, while trying the get token:

Java.Lang.IllegalStateException: 'Default FirebaseApp is not initialized in this process dk.xxxx.mobile. Make sure to call FirebaseApp.initializeApp(Context) first.'

Any help is appreciated

Collapse
 
serhii_korol_ab7776c50dba profile image
Serhii Korol

Check all settings it should work fine. I just checked this out and I didn't find any issues. Or describe your issue in more detail. Make steps to reproduce.

Collapse
 
arsen_pavliuk_ profile image
Arsen Pavliuk • Edited

HI, I had a same problem. I think you have to change google-services.json build action.** RMB on google-services.json => Property => Build Action => Select GoogleServiceJson**