Skip to content

Firebase Cloud Messaging push notification Add-on

This Add-on receives remote push notifications through Firebase Cloud Messaging (FCM) on Android. It wraps FirebaseMessaging of the Firebase Messaging SDK and provides device token issuance and deletion, retrieval of the message of the notification that launched the app, and events for message reception and token refresh. It does not process messages; it passes on the values that FCM delivered as they are.

The Add-on does not register issued tokens with the Hive Axyl server. Register tokens with UpsertTokenAsync of the Push module, and specify Fcm for ProviderType.

The Add-on does not declare or request the notification permission. To display notifications on Android 13 or later, declare the POST_NOTIFICATIONS permission in the app's manifest and have the app request it directly.

Module information

Item Value
Package com.com2usplatform.hiveaxyl.push.addon.fcm
Interface IFCMPlugin
Namespace Hive.Axyl.Push.Addon.FCM
Registration method AddFCM()
Supported platforms Android
Minimum requirements Android API 29+, Unity 6000.0+
Prerequisites

This Add-on does not initialize Firebase itself; it uses Firebase initialized with the Firebase configuration file included in the app. Place the google-services.json file downloaded from the Firebase console at Assets/Plugins/Android/google-services.json. During the build, the Add-on applies the Google services Gradle plugin to the generated Android project to incorporate this file. If the package_name in the file differs from the app's package name, the Gradle build fails. If the file is missing, only a build warning is displayed, and GetTokenAsync() and DeleteTokenAsync() return a Failure whose Code is FailedPrecondition instead of throwing an exception.

If your app also uses the Firebase Unity SDK, exclude the messaging feature of the Firebase Unity SDK. If this Add-on and the Firebase Unity SDK each register a service that receives messages, it is undetermined which service the OS delivers messages to.

Registration and retrieval

Register it together with the Push module in the registration step of HiveBootstrap.Initialize, and then retrieve it with HiveCore.TryResolve<T>().

using Hive.Axyl.Core;
using Hive.Axyl.Core.Unity;   // HiveBootstrap
using Hive.Axyl.Push;
using Hive.Axyl.Push.Addon.FCM;

HiveBootstrap.Initialize(config, builder =>
{
    builder.AddPush()
           .AddFCM();
});

if (HiveCore.TryResolve<IFCMPlugin>(out var fcm))
{
    // Code that runs only in Android builds
}
Not registered in the Unity Editor

This Add-on is registered only in players built for Android. In the Unity Editor, it is not registered even if you switch the platform to Android, so using HiveCore.Resolve<T>() throws RegistrationNotFoundException. Always check with TryResolve<T>() before you use it.

Method summary

Every method takes CancellationToken ct = default as the last parameter. For the calling conventions, see Call context.

Method Description
GetTokenAsync() Gets the FCM device token.
DeleteTokenAsync() Deletes the FCM device token.
GetColdStartMessageAsync() Gets the message of the notification that launched the app.

Methods

GetTokenAsync

Gets the current FCM device token with FirebaseMessaging.getToken(). The Add-on does not store the token, so it gets the token from Firebase every time you call this method.

Token issuance does not require the notification permission. The notification permission affects only whether received notifications are displayed. To get a token issued, Google Play services must be installed on the device.

Task<FcmServiceGetTokenResult> GetTokenAsync(CancellationToken ct = default)
Item Value
Response GetTokenResponse

Result cases — FcmServiceGetTokenResult

Result case Wire code Description
Success — The token was retrieved. The token is contained in Data.Token.
UnknownOutcome UNKNOWN A new result that this SDK version does not recognize.
Failure FAILURE The call could not be completed. Check the cause with the HiveError in Problem.

Distinguish the cause of a Failure by Problem.Code.

Problem.Code Cause
FailedPrecondition Firebase is not initialized. Check that google-services.json is included in the build.
Unavailable Google Play services is not on the device, or its version is too low. In this case, Problem.ExternalCode is PLAY_SERVICES_MISSING. This code also applies when the connection to the FCM service failed because of a network connection problem.
Cancelled The call was canceled with the CancellationToken.
Unknown Another Firebase error occurred.

Call example

Subscribe to the TokenRefreshed event first so that you can register the token again if it changes later, and then get the token and register it.

using Hive.Axyl.Push;
using Hive.Axyl.Push.Addon.FCM;

fcm.TokenRefreshed += newToken =>
{
    // Register the new token again with UpsertTokenAsync.
};

var tokenResult = await fcm.GetTokenAsync();

if (tokenResult is FcmServiceGetTokenResult.Success token)
{
    var result = await push.UpsertTokenAsync(new UpsertTokenRequest
    {
        Token        = token.Data.Token,
        ProviderType = UpsertTokenRequestProviderType.Fcm,
        // Also specify TimezoneId, Country, Language, and Agreement.
    });
}

DeleteTokenAsync

Deletes the current FCM device token with FirebaseMessaging.deleteToken(). If you call GetTokenAsync() after the deletion, you get a new token, and when FCM issues a new token, it is also delivered through the TokenRefreshed event.

This method does not change the token registered with the Hive Axyl server. To detach the token registered with the Hive Axyl server from the user, see DetachTokenIdentifierAsync.

Task<FcmServiceDeleteTokenResult> DeleteTokenAsync(CancellationToken ct = default)
Item Value
Response DeleteTokenResponse

Result cases — FcmServiceDeleteTokenResult

Result case Wire code Description
Success — The token was deleted.
UnknownOutcome UNKNOWN A new result that this SDK version does not recognize.
Failure FAILURE The call could not be completed. Check the cause with the HiveError in Problem.

Distinguish the cause of a Failure by Problem.Code.

Problem.Code Cause
FailedPrecondition Firebase is not initialized. Check that google-services.json is included in the build.
Unavailable The connection to the FCM service failed because of a network connection problem.
Cancelled The call was canceled with the CancellationToken.
Unknown Another Firebase error occurred.

GetColdStartMessageAsync

If the app user tapped a notification while the app was not running and the app launched as a result, returns the message of that notification. This method returns the message only on the first call after the app launches, so it does not return the message of a notification tapped while the app is running. Call it once when the app starts.

The Notification field of the returned message can be empty. Read the values to process for the tapped notification from Data, not from the notification content.

Even if there is no message to return, Data.Message is not null but a message with empty fields. To check whether the app was launched by a notification tap, check that Data.Message.MessageId is not empty. If the app was launched without a notification, or on the second and later calls, an empty message is returned.

Task<FcmServiceGetColdStartMessageResult> GetColdStartMessageAsync(CancellationToken ct = default)
Item Value
Response GetColdStartMessageResponse

Result cases — FcmServiceGetColdStartMessageResult

Result case Wire code Description
Success — The retrieval succeeded. If no notification launched the app, Data.Message is an empty message.
UnknownOutcome UNKNOWN A new result that this SDK version does not recognize.
Failure FAILURE The call could not be completed. Check the cause with the HiveError in Problem.

Call example

using System.Collections.Generic;
using Hive.Axyl.Push.Addon.FCM;

var result = await fcm.GetColdStartMessageAsync();

if (result is FcmServiceGetColdStartMessageResult.Success success
    && !string.IsNullOrEmpty(success.Data.Message.MessageId))
{
    FcmRemoteMessage launchMessage = success.Data.Message;   // Message of the notification that launched the app
    IReadOnlyDictionary<string, string> data = launchMessage.Data;
}

Events

Both events are invoked on the engine main thread, so you can use engine APIs inside the handlers. An event is delivered only to the handlers subscribed at the time it is raised, and events raised before you subscribe are not delivered again later.

NotificationReceived

Raised when FCM delivers a message through FirebaseMessagingService.onMessageReceived. When the app is in the foreground, it is raised for every message; when the app is in the background, it is raised only for data-only messages without notification content. Notification messages that arrive while the app is in the background are displayed by the OS directly, so this event is not raised for them.

Notifications that the app server sends with Send remote push notifications always contain notification content, so this event is raised when the app is in the foreground. Messages received in the foreground are not displayed as system notifications, so if you want to display them, the app must display them itself.

event Action<FcmRemoteMessage> NotificationReceived
Parameter Type Description
— FcmRemoteMessage The message delivered by FCM.

TokenRefreshed

Raised when FCM issues a new device token through FirebaseMessagingService.onNewToken. The Add-on does not register the new token with the Hive Axyl server, so register the token you receive through the event again with UpsertTokenAsync.

event Action<string> TokenRefreshed
Parameter Type Description
— string The newly issued FCM device token.

Data types

DeleteTokenResponse

No fields.

FcmNotification

The raw information of RemoteMessage.Notification. Fields without a value are empty strings or empty lists. For a data-only message without notification content, all fields are empty.

Field Type Required Description
Title string Required The getTitle() value, which is the notification title.
Body string Required The getBody() value, which is the notification body.
ImageUrl string Required The getImageUrl() value, which is the notification image URL.
Icon string Required The getIcon() value, which is the resource name of the notification icon.
Sound string Required The getSound() value, which is the name of the notification sound.
Tag string Required The getTag() value, which is the notification tag. A notification with the same tag is replaced by the new notification.
ClickAction string Required The getClickAction() value, which is the action to run when the notification is tapped.
ChannelId string Required The getChannelId() value, which is the Android notification channel ID.
Color string Required The getColor() value, which is the notification icon color in #rrggbb format.
Link string Required The getLink() value, which is the link attached to the notification.
TitleLocKey string Required The getTitleLocalizationKey() value, which is the localization string key to use for the notification title.
TitleLocArgs IReadOnlyList<string> Required The getTitleLocalizationArgs() value, which is the list of arguments to insert into the title localization string.
BodyLocKey string Required The getBodyLocalizationKey() value, which is the localization string key to use for the notification body.
BodyLocArgs IReadOnlyList<string> Required The getBodyLocalizationArgs() value, which is the list of arguments to insert into the body localization string.

FcmRemoteMessage

The raw information of com.google.firebase.messaging.RemoteMessage. The app is responsible for interpreting it, such as deciding whether to prioritize the notification content or the data and how to extract deep links.

Field Type Required Description
MessageId string Required The getMessageId() value, which is the message ID. An empty string if GetColdStartMessageAsync() returns an empty message.
SentTimeUnixMillis long Required The getSentTime() value, which is the time the message was sent. In Unix epoch milliseconds.
SentTime DateTimeOffset Required SentTimeUnixMillis converted to a UTC DateTimeOffset.
From string Required The getFrom() value, which is the sender of the message.
CollapseKey string Required The getCollapseKey() value, used to collapse messages with the same key into one.
Priority int Required The getPriority() value, which is the priority at which the message was delivered. 0 means unknown, 1 means high, and 2 means normal.
TtlSeconds int Required The getTtl() value, which is the time to live of the message. In seconds.
Ttl TimeSpan Required TtlSeconds converted to a TimeSpan.
Data IReadOnlyDictionary<string, string> Required The getData() value, which is the data contained in the message. The data that the app server sent in options.customData of Send remote push notifications is contained here. An empty dictionary if there is no data.
Notification FcmNotification Required The getNotification() value, which is the notification content. For a data-only message, all fields are empty.

GetColdStartMessageResponse

Field Type Required Description
Message FcmRemoteMessage Required The message of the notification that launched the app. If there is no message to return, it is not null but a message with empty fields; tell them apart by whether MessageId is empty.

GetTokenResponse

Field Type Required Description
Token string Required The FCM device token. Put it in UpsertTokenRequest.Token of the Push module. Because it is sensitive information, it is not recorded in plain text in SDK logs.