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