⏰Scheduling FCM Push Notifications🔔 On Device — Android📱

In this article, We will schedule On Device FCM (Firebase Cloud Messaging) Push Notifications without using Cloud Pub/Sub or Cron jobs.

Shreyas Patil
MindOrks

--

Hello everyone, If you’re developing an app where you want to send scheduled Notifications to users then you can achieve in many ways. You can use Google Cloud Pub/Sub using Firebase Cloud Functions. Cloud Pub/Sub and Cron jobs are costly solutions. In this demo, we’ll schedule FCM Notifications by just sending normal Push Notification to subscribed channel and we’ll process/schedule it on the device.

# What will we do?

  • We’ll subscribe to FCM Topic.
  • We’ll send Data payload with scheduling information to the FCM topic.
  • Process received notification in a device, Schedule it using AlarmManager.
  • At the Scheduled time, create WorkManager for background processing and display notification on the system tray.

# What are the Advantages of using this technique? 😕

Imagine you have developed XYZ app which is related to Online Shopping and you always provides exciting discount/offers to users. It has 5000 active user installs. Imagine Following 2 Scenarios with respect to the above data.

#1️⃣Scenario 1:

You have scheduled a 50% discount offer notification to send on 12:00 am using Google Cloud Pub/Sub. This offer is going to expire in 5 minutes. Out of 5000 users, only 3000 users are online at that time. Remaining 2000 users will receive notification after they’ll turn on data and till that time, the offer will be expired!😔 Thus, you’ll lose 2000 users 😐.

#️2️⃣Scenario 2:

You have scheduled a 50% discount offer notification to send on 12:00 am using the method we discussed earlier. Suppose we sent Data payload on 09:00 pm (i.e. Before 3 hours). In between that time period. All online users will receive payload on device and notification will be scheduled. Consider, out of 5000 users, 4500 users were online between 9 pm to 12 am. Then all these 4500 users will receive a notification. Most exciting🤩 will be… Though users are offline on 12 am still notification is displayed (because they already received notification earlier on device). Thus we’ll not lose many users.😀

Thus from above both scenarios, the Second scenario seems efficient and useful for some use cases. Let’s implement it!

💻 Implementation

I have created a repository on GitHub. You can take reference of it.

  • Set up Project on Firebase Console
  • Download a google-services.json configuration file and paste it in /app directory of the project.
  • Add dependencies in build.gradle of app module.
dependencies {
implementation 'androidx.appcompat:appcompat:1.1.0'
//Firebase
implementation 'com.google.firebase:firebase-core:17.2.1'
implementation 'com.google.firebase:firebase-iid:20.0.2'
implementation 'com.google.firebase:firebase-messaging:20.1.0'

// Work Manager
implementation 'android.arch.work:work-runtime:1.0.1'
}
  • Service and BroadcastReceiver declarations in Manifest:
<service
android:name=".fcm.MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>

<receiver android:name=".fcm.NotificationBroadcastReceiver" />
  • In MainActivity.kt, subscribe to FCM Notification Channel. Let’s say we’re subscribing to discount-offers FCM Channel.

Let’s Understand Format of Data Payload:

We’ll send FCM Data payload as below.

{ 
"to": "/topics/discount-offers",
"priority": "high",
"data" : {
"title" : "TITLE_HERE",
"message" : "MESSAGE_HERE",
"isScheduled" : "true",
"scheduledTime" : "2019-12-13 09:41:00"
}
}

When we send payload, if isScheduled is false then the notification is displayed instantly otherwise it’s displayed on scheduledTime.

Format of scheduledTime: YYYY-MM-DD HH:MM:SS.

  • In MyFirebaseMessagingService , whenever Notification is received, onMessageReceived() is invoked. We have to do all the process of scheduling in this method. We have to parse data.

We’ll first parse data like title, message, etc. We’ll check if `Automatic Date and Time` is turned ON in system settings (otherwise notification can be displayed at the wrong time). Then check if isScheduled is true then schedule notification otherwise display the notification.

Let’s come to scheduleAlarm() .

Set One-time Alarm using AlarmManager

We’re using AlarmManager to set one-time (non-repeating) Alarm. We have parsed scheduledTime using SimpleDateFormat class to get its millisecond value.

Finally, we have scheduled alarm using set() method. It sets non-repeating one time alarm in the system and executes exactly on specified millies value.

RTC_WAKEUP flag will trigger the alarm according to the time of the clock which will wake up the device when it goes off. At that time, onReceive() ofNotificationBroadcastReceiver will be executed. Let’s see an implementation of it.

NotificationBroadcastReceiver Implementation

In this, we’ll get data from the Intent and create WorkManager data. We’ll create OneTimeWorkRequest because this work should only be executed once. In the end, we’ll enqueue work and execution of Work will be started. Thus, doWork() method of ScheduledWorker is executed.

ScheduledWorker Implementation

In that, we’ll get data(like title, message, etc) which we received from notification and finally, we’ll display it on the system tray. Other background tasks will also be processed here. If the process is successful, return using Result.success() . If you want to retry process simple return Result.retry() otherwise return Result.failure() .

Hurrah! 😍 we have successfully implemented and scheduled FCM Push Notification on Android device.

# What If Device is Rebooted?😕

If a device is rebooted, Alarm will not work. For this, you’ll have to store all the information about FCM Notifications using Room database. After this, you’ll need to create a receiver (ON_BOOT_COMPLETED) which will be executed when Device is Rebooted. In that, all notifications in Room database should be scheduled again using AlarmManager.

Let’s Test It 😃

I have sent below payload with to the FCM Channel (discount-offers).

{ 
"to": "/topics/discount-offers",
"priority": "high",
"data" : {
"title" : "🎅 Christmas Offer 🎄",
"message" : "Grab 90% Discount 😍 on Mobile Phones",
"isScheduled" : "true",
"scheduledTime" : "2019-12-13 14:12:00"
}
}

🚀See output below and notice that Internet/Wi-Fi is OFF still at exactly 02:12 pm I’m getting a notification on the system tray 😃.

At exact 02:12, Notification is displayed though Data is OFF.

Yippie 😍! It’s working as expected. Hope you liked that. If you find it helpful please share this article. Maybe it’ll help someone needy!

Sharing is Caring!

Support this repository:

Thank you 😄!

If you want to contact me, feel free to reach me…

--

--

Shreyas Patil
MindOrks

Google Developer Expert for Android, 👨‍💻Engineer @ Paytm ❤️ Android & Kotlin | More info: https://shreyaspatil.dev