Push notifications play an important role in user engagement and retention in your mobile app, keeping users up to date and creating a sense of urgency that leads to purchases. And in Android, we get the added benefit of Firebase Cloud Messaging (FCM) notification service, which acts as a middleman between the app server and the user’s Android device. It helps the delivery of push notifications, even if the app is not active or the user is using a different app on their device.
Firebase Cloud Messaging (FCM) is used to send data messages and alerts to users, thanks to its robust cross-messaging system. iOS, Web and Android platforms are all supported by FCM. Messages with a data payload of up to 4kb can be sent using FCM push notifications.
In this article, we will explore the step-by-step integration of push notifications into Android apps, and discuss the critical aspects of implementation. We will also introduce several products and tools that can simplify and amplify user engagement.
Understanding Android Push Notifications
Mobile push notifications help to improve user engagement, customer retention, and overall user experience in your applications. When push notifications are used properly, they can significantly enhance the effectiveness of mobile apps across various business domains.
Push notifications can be used for different use cases and purposes in your Android app, including:
i) Updating a user on the status of their online booking or schedule.
ii) Provide clarifications and updates for an online order the user has placed.
iii) Advising users of changes in the back-end and helping them track their package.
iv) Creating hype around events linked to the app, and introducing a user to new offers, promotions and opportunities.
v) Encouraging users to try new app features with teasing messages and notifying them of server updates and other back-end changes.
Implementation Approach of Push Notifications in Android Application
Prerequisites
You need to have these tools and services in order to successfully implement push notifications in your Android app FCM:
i) Android Studio – This is the IDE used for the Android development.
ii) Basic Knowledge & Understanding – You need a basic understanding of Android project development and structure, and manifest file configuration.
iii) A Firebase Account – You should have a Firebase account for creating and managing your project settings.
iv) Internet Availability – Integration testing and firebase setup require an internet connection.
Step 1. Setup your Firebase Project
Visit Firebase Console.
Create your project by Giving it a name and Click continue.
For further configuration, you can enable or disable the Google Analytics service to get the data analytics for your app.
To complete the setup you need to review the project settings; then you can create your project.
After you have created your project, you need to do additional project configuration for the push notification implementations.
Registering your app in project dashboard
You need to click on the Android icon in the dashboard to add an Android app. Next, enter a Android package name. This package name must be the same as the package name in your project (i.e., com.app.demoapp
).
You can also enter your app’s nickname to identify your app in the console.
Add SHA-1 key for your app. You need to use this command to generate your SHA-1 key in your terminal: Now copy the SHA-1 key and paste it into the Firebase console.
./gradlew signingReport
Finally Click ‘Register App’ to finish configuration.
Setup Google Services
Once you finish registering your app, you can download the google-services.json
file and save this it to your computer.
Now you need to add google-services.json
to your Android project, file to the app
directory of your Android project.
MyApp/
├── app/
│ ├── src/
│ ├── build.gradle
│ ├── google-services.json
├── build.gradle
├── settings.gradle
Add Firebase SDK
Next, add Firebase SDK to Your Project, in build.gradle
add the Google services classpath:
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
// Add this line
classpath 'com.google.gms:google-services:4.3.10'
}
}
in app/build.gradle
add the following dependencies:-
apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'
android {
// ...
}
dependencies {
// Add these lines
implementation platform('com.google.firebase:firebase-bom:29.0.4')
implementation 'com.google.firebase:firebase-analytics'
implementation 'com.google.firebase:firebase-messaging'
}
After you finish these steps you can click ‘Sync Now’ in the Android Studio to sync your project with the Firebase.
Step 2. Configure Your Android Project
Project-Level build.gradle
Open Your Project-Level build.gradle
: Navigate to the root directory of your Android project and locate the build.gradle
file.
Ensure the google()
and mavenCentral()
repositories are included in the repositories
section.
buildscript {
repositories {
// Check that you have these lines
google()
mavenCentral()
}
dependencies {
// Add this line
classpath 'com.google.gms:google-services:4.3.10'
}
}
allprojects {
repositories {
// Check that you have these lines
google()
mavenCentral()
}
}
Make changes in the build.gradle
Find and locate the build.gradle
file in your project app directory, then add the google-services
plugin at the end of the file, and add the Firebase and Firebase Messaging dependency in the dependencies
section.
apply plugin: 'com.android.application'
android {
compileSdkVersion 33
defaultConfig {
applicationId "com.example.myandroidapp"
minSdkVersion 21
targetSdkVersion 33
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.8.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
// Add Firebase BOM
implementation platform('com.google.firebase:firebase-bom:29.0.4')
// Add Firebase Messaging dependency
implementation 'com.google.firebase:firebase-messaging'
}
// Add this line at the bottom of the file
apply plugin: 'com.google.gms.google-services'
With these steps completed, your project is configured with Firebase dependencies, including Firebase Messaging for push notifications. Let us now proceed with Firebase Messaging service setup and handling the notifications in your app.
Step 3. Implement the FCM
Add a Service to Handle FCM Messages
Create a new class named MyMessagingService
that extends FirebaseMessagingService
.
You need to override onMessageReceived
Method to handle incoming messages when your app is in foreground state. Then implement logic to handle the notification and optionally show it to the user.
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import androidx.core.app.NotificationCompat;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
public class MyMessagingService extends FirebaseMessagingService {
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// Handle the received message
if (remoteMessage.getNotification() != null) {
// Get the message body
String messageBody = remoteMessage.getNotification().getBody();
// Send a notification
sendNotification(messageBody);
}
}
private void sendNotification(String messageBody) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
String channelId = getString(R.string.default_notification_channel_id);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle(getString(R.string.app_name))
.setContentText(messageBody)
.setAutoCancel(true)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId, "Channel human readable title", NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(channel);
}
notificationManager.notify(0, notificationBuilder.build());
}
}
Register in AndroidManifest.xml
file
Open the AndroidManifest.xml
file in your project.
Now you need to register the MyMessagingService
in the manifest to handle FCM messages.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myandroidapp">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<!-- Add this service -->
<service
android:name=".MyMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<!-- Other activities and services -->
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Step 4: Obtain the FCM Registration Token
To receive push notifications, your app needs to obtain the FCM registration token. This token uniquely identifies the app instance on the device.
Code Example to Fetch the Device Token
You can fetch the FCM registration token in your FirebaseMessagingService
or any other appropriate place in your app. Let’s see how to do it in FirebaseMessagingService
.
Update MyMessagingService
:
import android.util.Log;
import com.google.firebase.messaging.FirebaseMessaging;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
public class MyMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// Handle the received message
if (remoteMessage.getNotification() != null) {
// Get the message body
String messageBody = remoteMessage.getNotification().getBody();
// Send a notification
sendNotification(messageBody);
}
}
@Override
public void onNewToken(String token) {
Log.d(TAG, "Refreshed token: " + token);
// Send the token to your server or save it as needed
sendRegistrationToServer(token);
}
private void sendNotification(String messageBody) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
String channelId = getString(R.string.default_notification_channel_id);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle(getString(R.string.app_name))
.setContentText(messageBody)
.setAutoCancel(true)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId, "Channel human readable title", NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(channel);
}
notificationManager.notify(0, notificationBuilder.build());
}
private void sendRegistrationToServer(String token) {
// TODO: Implement this method to send the token to your app server.
// This can be an API call to store the token on your server
}
}
You can fetch the token in an Activity or Fragment, and store or use it as required.
import android.os.Bundle;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
import com.google.firebase.messaging.FirebaseMessaging;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Fetch the token
FirebaseMessaging.getInstance().getToken()
.addOnCompleteListener(task -> {
if (!task.isSuccessful()) {
Log.w(TAG, "Fetching FCM registration token failed", task.getException());
return;
}
// Get new FCM registration token
String token = task.getResult();
// Log and toast
Log.d(TAG, "FCM Registration Token: " + token);
// You can send this token to your server or store it as needed
});
}
}
Using these methods you can get the FCM registration token in your Android app. The token can be fetched either in the FirebaseMessagingService
or any Activity or Fragment. This token is important for sending targeted push notifications to specific devices.
Step 5: Send Push Notifications
If you want to send notifications from a server you need to make a POST request to FCM API.
You need to Get a Server Key
- In the Firebase Console → Project Settings → “Project Overview” → “Cloud Messaging”.
- In “Project credentials”, you will find the Server key.
cURL Request: This cURL command will be used to send notifications. Replace <YOUR_SERVER_KEY>
with your actual server key and <FCM_DEVICE_TOKEN>
with the FCM token of the target device.
//CURL request to send push notifications
curl -X POST \
https://fcm.googleapis.com/fcm/send \
-H "Authorization: key=<YOUR_SERVER_KEY>" \
-H "Content-Type: application/json" \
-d '{
"to": "<FCM_DEVICE_TOKEN>",
"notification": {
"title": "Notification",
"body": "Notification sent from server"
},
"data": {
"key1": "value1",
"key2": "value2"
}
}'
-
https://fcm.googleapis.com/fcm/send
API endpoint. -
H "Authorization: key=<YOUR_SERVER_KEY>"
: This is an authorization header with your server key. -
H "Content-Type: application/json"
: content type header. -
d '{ ... }'
: This is the JSON payload that has your notification and data.
Advanced Topics
Handling Data Messages
Data messages are a type of message that can carry custom key-value pairs and are handled differently from notification messages. Data messages are received in the onMessageReceived
method of FirebaseMessagingService
, regardless of whether the app is in the foreground or background.
Example for Handling Data Messages
Update MyMessagingService
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.util.Log;
import androidx.core.app.NotificationCompat;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
public class MyMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// Check if message contains a notification payload
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
sendNotification(remoteMessage.getNotification().getBody());
}
// Check if message contains a data payload
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
handleNow(remoteMessage.getData());
}
}
@Override
public void onNewToken(String token) {
Log.d(TAG, "Refreshed token: " + token);
sendRegistrationToServer(token);
}
private void handleNow(Map<String, String> data) {
// Process the data here
String key1 = data.get("key1");
String key2 = data.get("key2");
// Handle the data accordingly
}
private void sendNotification(String messageBody) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
String channelId = getString(R.string.default_notification_channel_id);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle(getString(R.string.app_name))
.setContentText(messageBody)
.setAutoCancel(true)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId, "Channel human readable title", NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(channel);
}
notificationManager.notify(0, notificationBuilder.build());
}
private void sendRegistrationToServer(String token) {
// Implement this method to send token to your app server
}
}
Managing Notification Channels
Starting with Android 8.0 (API level 26), all notifications must be assigned to a channel. This allows users to control notification settings for each channel.
Example for Creating Notification Channels
Create a Method to Set Up Notification Channels:
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.os.Build;
public class NotificationUtils {
public static final String CHANNEL_ID = "default_channel_id";
public static final String CHANNEL_NAME = "Default Channel";
public static final String CHANNEL_DESCRIPTION = "This is the default notification channel";
public static void createNotificationChannel(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
CHANNEL_ID,
CHANNEL_NAME,
NotificationManager.IMPORTANCE_DEFAULT
);
channel.setDescription(CHANNEL_DESCRIPTION);
NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
}
Call This Method in Your MainActivity
or Application Class:
javaCopy code
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Create notification channel
NotificationUtils.createNotificationChannel(this);
}
}
Alternatively, you can call NotificationUtils.createNotificationChannel(this);
in your Application
class if you have one:
import android.app.Application;
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
// Create notification channel
NotificationUtils.createNotificationChannel(this);
}
}
Update Your Notification Builder to Use the Channel ID:
private void sendNotification(String messageBody) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
String channelId = NotificationUtils.CHANNEL_ID;
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle(getString(R.string.app_name))
.setContentText(messageBody)
.setAutoCancel(true)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notificationBuilder.build());
}
Testing Push Notifications
When push notifications are implemented, we need to do testing to make sure they are implemented correctly.
In Android Studio, you can open the logcat, View > Tool Windows > Logcat
.
We can also filter the logcat output using the tag we used in the FirebaseMessagingService
class. The application must be running on device or through an emulator.
When the notification is received, we can see the data in logcat like this:
D/MyFirebaseMsgService: Message Notification Body: This is a test notification!
Message data can be seen like this:
D/MyFirebaseMsgService: Message data payload: {key1=value1, key2=value2}
Conclusion
In this article we learned about push notifications, along with a step-by-step approach to implementation. We learned how to set up a project in Firebase console and how to complete the required configuration in Firebase project settings, so you can start sending Android notifications to your Android users.
You need to start by setting up a Firebase project and downloading the google-services.json
file. After that, you need to put this file app’s directory and modify the build.gradle
files to include Firebase dependencies.
Then, you need to create a class that will handle the incoming messages and register this service class in the AndroidManifest.xml
. After adding the service in manifest file, you need to fetch the FCM token that is used to uniquely identify your app, so a notification can be sent to the targeted device.
Notifications can be tested by sending messages from the Firebase Console and using Android Studio’s logcat to confirm delivery. To activate server-side notifications, use a cURL request with your Firebase server key and the device’s FCM token.
To maintain compatibility with later Android versions, you’ll need to process data messages in your ‘FirebaseMessagingService` and manage notification channels for sophisticated configurations.
Push notifications, which offer relevant updates and customized information – and can increase user retention and conversion rates – are crucial for encouraging user engagement.
Read the official Firebase and Android SDK docs for more information and in-depth directions. These websites provide thorough guidance and industry-best practices for incorporating push notifications into your application.
Top comments (0)