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>().
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.
| 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.
| 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.
| 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.
| 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.
| 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. |