Android - Notifications
Notification handling is a frequent request we encounter. Recognizing that not all developers are accustomed to Android's specific way of managing notifications, we have decided to provide additional information and tutorials to assist in this area.
Setup
Set the push
flag to true
In the settings.json
file, ensure the push
flag is set to true. This activates push
notification functionality for the app.
"push": true
Enable Q2PushService
in mob_modules
In the mob_modules
section, ensure the Q2PushService
module is included and set to
enabled: true
. This module handles core push notification services.
{
"id": 1,
"name": "Q2PushService",
"moduleType": "push",
"classPath": "com.app.q2.modules.push.q2_push_service.Q2PushService",
"include": ":modules:q2_push_service",
"googleServicesRequired": "true",
"data": {},
"enabled": true
}
Enable PushEnrollment
in sdk_modules
In the sdk_modules
section, enable the PushEnrollment
module, which handles the push
enrollment process (i.e., prompting the user to opt-in for push notifications).
{
"name": "PushEnrollment",
"identifier": "pushEnrollment",
"classPath": "com.q2.push.enrollmentprompt.EntryPoint",
"include": ":modules:push",
"data": {},
"enabled": true
}
Once these settings are applied, the DevApp will be set up to use push notifications, allowing you to receive notifications and manage the push enrollment flow.
How the Q2 Mobile App Handles Notifications
The handling of notifications varies based on the application's state, which can either be backgrounded or foregrounded.
Backgrounded: If the application is in the background (either minimized or closed),
the operating system takes the initial responsibility of handling the notification. This
is why you see the notification at the top of your device, given that a message and title
are provided. Upon clicking, it launches the Activity marked as the LAUNCHER of the
application. This activity seizes the intent and forwards it to your module via the
LifecycleModule.willHandleNewIntent()
method.
Foregrounded: Conversely, when the application is in the foreground, our
FirebaseMessagingService
directly receives the message and forwards it to the
PushReceiverModule.willConsumeNotification()
. If the notification isn't consumed at this
stage, and no other entity does so, the FirebaseMessagingService
will try to display the
notification, provided a title and body exist. If these elements are absent, no
notification will be displayed.
Given that the application's state influences how notifications are consumed, it's
recommended to construct your module using both the LifecycleModule
and the
PushReceiverModule
. This approach ensures that notifications are handled effectively in
both states.
For a practical example of best practices, please refer to the android-rtu-notification-deeplink example in the RTU (Ready-to-Use) section.
Notification Channels
As of Android 8.0, Notification Channels are a way to modify the notification displayed to the user.
Mobile SDK allows you to create your own notification channels. This is done by using the
createNotificationChannel()
method in the PushReceiverModule
. This method provides you
with the NotificationManager
.
val channel = NotificationChannel(
NOTIFICATION_CHANNEL_ID,
channelName,
channelImportance
).apply {
description = channelDescription
}
notificationManager?.createNotificationChannel(channel)
Once the notification channel is created, it can be referred to in the notification
builder. This is achieved by invoking the setChannelId()
method in the
NotificationCompat.Builder
and passing the channel ID as the argument.
Notification Message
Firebase notifications have a specific structure that must be followed. The following is an example of a standard notification payload which contains a title and body:
{
"message": {
"token": "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"notification": {
"title": "My Mobile SDK Test Message",
"body": "Mobile SDK is amazing!"
}
}
}
You can also send data type notifications. These notifications are used to send data to the device without displaying a notification:
{
"message": {
"token": "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"data": {
"myUri": "messages"
}
}
}
You also have the option to consolidate them into a single message. This is beneficial when you aim to display a notification while simultaneously sending data to the device.
Any values transmitted in the data object can be accessed either from the Intent
parameter in LifecycleModule.willHandleNewIntent()
or from the RemoteMessage
parameter
in PushReceiverModule.willConsumeNotification()
.