Skip to main content

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