Android offers many great battery-saving features such as Doze mode, but the optimizations can affect how and when your app receives notifications. If you’re not using Firebase Cloud Messaging correctly, some aspects of Doze mode or how you’re processing your FCM messages could delay notification delivery times to your end users.
To ensure your FCM messages are resulting in push notifications to your users reliably, you must ensure you’re setting the right priority for your FCM messages and ensure you’re using the right constructs to process the FCM payload. Read on below to learn how to do this effectively.
Make sure you’re setting the right priority for your user visible notifications
You may not have known but normal priority FCM message delivery times can be impacted by additional battery optimizations that occur when the screen is off such as Doze mode. Let’s learn more about message priorities and when to use which:
FCM messages have two priority levels - normal priority and high priority.
-
Normal priority messages are delivered promptly when the device’s screen is on and batched together and delivered opportunistically when the device is in Doze mode. Doze mode only happens when the screen is off. Use this priority when you want to send an FCM message that does not result in a user visible notification, or the user visible notification is not time sensitive. For example, sending a notification for when a non time sensitive bank statement is ready for viewing.
-
High priority FCM attempts to deliver high priority messages immediately, allowing FCM to wake a sleeping device when necessary. This priority is ideal for FCM messages that result in immediate user visible notification - for example for real time message communications or a time sensitive alert to the user. But there might be other scenarios in which using a high priority setting is recommended.
Deciding between high priority and normal priority messages
Since normal priority delivery times can be impacted by Doze mode, it might make sense to lean towards setting high priority for most user visible notifications to ensure they are delivered promptly to your users. For example, while use cases like issuing a non time sensitive bank statement notice might make sense as a normal priority notification, other use cases might be better matched to high priority notifications - such as a fraudulent credit card charge notification, chat message notifications, or food delivery updates.
Setting notification priority for your messages
There are three ways to send notifications to your users:
- From your server using the Firebase Admin SDK
- From your server using the FCM REST API
- From the Firebase Messaging dashboard in the Firebase console
Both the Firebase Admin SDK and using the REST API methods are very similar as they both simply require updating the message JSON payload. The code snippet below shows how to explicitly set the priority to high just in case. Note that for notifications sent from the console, setting Android-specific notification fields isn’t supported.
{
"message": {
"notification": {
"body": "Purchase exceeding $500 detected",
"title": "Credit card purchase"
},
"data": {
"purchaser": "Your child",
"items": "Gravity Defier Sneakers"
},
"android": {
"priority": "high"
},
"apns": {
"headers": {
"apns-priority": "5"
}
}
}
}
Are there any limits on the number of high priority notifications I can send?
High priority messages are only limited if they’re used for messages that don’t result in a user visible notification. For example, if you use high priority messages to update a “recipient is typing a message now” indicator, you might find many high priority messages are delayed, including the more important chat notification messages. As a result it is important to ensure that high priority push messages result in a user visible notification or the app being opened into the foreground. If you’re using a high priority setting for messages that don’t result in a user visible notification, like a data message or a notification sent to a user who has blocked notifications from your app, your notification could get throttled and deprioritized.
Ensure your message payloads get processed in time
For both high priority and normal priority messages received on an Android device, several seconds are given to process the message payload in the onMessageReceived handler, with slightly more time allocated for high priority messages than normal priority ones. This time is only expected to be long enough to immediately render a notification. If you have to do any additional work such as loading an image from device storage or calling your servers to collect additional content you will need to take additional steps.
The onMessageReceived
method is called on a separate worker thread. As best practice, you should process the message payload and display a notification immediately within the onMessageReceived
method. You should not be making additional asynchronous network calls or doing payload processing on a separate thread within the onMessageReceived
method, doing so can cause your application to be outside of a valid process lifecycle before the payload is fully processed. If this happens, you may see that certain FCM messages that are sent result in delayed or missing notifications.
If you do need additional time to process for your message, for example to fetch an image based on an imageUrl contained in your message payload, you will need to use a construct such as WorkManager or foreground service to extend the application lifecycle. You should follow the guidance below when you override the onMessageReceived
method to ensure your notifications get fully processed.
For high priority notifications
Start an expedited job using the Android WorkManager to ensure that your high priority notification gets prioritized processing time to ensure your notification rendering runs to completion.
The good news is that if you’re worried about exhausting expedited job quotas as a result of high priority FCM processing, you don’t need to be. There is a brief exemption for expedited jobs scheduled immediately after a high priority FCM onMessageReceived is dispatched.
For normal priority notifications
Start a regular WorkRequest using the Android WorkManager instead. This will ensure that the additional work required to process your notification will get processed eventually, without utilizing prioritized processing and causing unneeded battery usage issues.
Test your high priority notifications in Doze mode
To ensure your high priority notifications are correctly being received and processed when a user receives it on their device when in Doze mode, you should test it out.
Follow these instructions to test your notifications:
-
Set your device in Doze mode: Refer to these instructions to enable Doze mode on your test device.
-
Get the FCM token: Retrieve the registered FCM token from your app running on a test device. Refer to these docs for instructions on how to get the token.
-
Send the notification: Once you have the FCM token, send your high priority notification to the test device using either your FCM notification sending code (using the Admin SDK is recommended), or a cURL command with configuration parameters matching your high priority notification
Thrill your users with your efficient and consistent notifications
Follow the guidance above to make sure that your notifications are getting fully processed and reaching your users as intended. Your users will appreciate receiving timely notifications that enhance their app experience while also maximizing and being mindful of their battery life.