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.
./gradlew signingReport
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.
MyApp/ ├── app/ │ ├── src/ │ ├── build.gradle │ ├── google-services.json ├── build.gradle ├── settings.gradle
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.
buildscript { repositories { google() mavenCentral() } dependencies { // Add this line classpath 'com.google.gms:google-services:4.3.10' } }
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:
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' }
You can fetch the token in an Activity or Fragment, and store or use it as required.
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() } }
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
./gradlew signingReport
- https://fcm.googleapis.com/fcm/send API endpoint.
-
H "Authorization: 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
MyApp/ ├── app/ │ ├── src/ │ ├── build.gradle │ ├── google-services.json ├── build.gradle ├── settings.gradle
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:
buildscript { repositories { google() mavenCentral() } dependencies { // Add this line classpath 'com.google.gms:google-services:4.3.10' } }
Call This Method in Your MainActivity or Application Class:
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' }
Alternatively, you can call NotificationUtils.createNotificationChannel(this); in your Application class if you have one:
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() } }
Update Your Notification Builder to Use the Channel ID:
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'
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:
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()); } }
Message data can be seen like this:
<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>
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.
The above is the detailed content of Android Push Notifications Step by Step Guide. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undress AI Tool
Undress images for free

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Java supports asynchronous programming including the use of CompletableFuture, responsive streams (such as ProjectReactor), and virtual threads in Java19. 1.CompletableFuture improves code readability and maintenance through chain calls, and supports task orchestration and exception handling; 2. ProjectReactor provides Mono and Flux types to implement responsive programming, with backpressure mechanism and rich operators; 3. Virtual threads reduce concurrency costs, are suitable for I/O-intensive tasks, and are lighter and easier to expand than traditional platform threads. Each method has applicable scenarios, and appropriate tools should be selected according to your needs and mixed models should be avoided to maintain simplicity

In Java, enums are suitable for representing fixed constant sets. Best practices include: 1. Use enum to represent fixed state or options to improve type safety and readability; 2. Add properties and methods to enums to enhance flexibility, such as defining fields, constructors, helper methods, etc.; 3. Use EnumMap and EnumSet to improve performance and type safety because they are more efficient based on arrays; 4. Avoid abuse of enums, such as dynamic values, frequent changes or complex logic scenarios, which should be replaced by other methods. Correct use of enum can improve code quality and reduce errors, but you need to pay attention to its applicable boundaries.

JavaNIO is a new IOAPI introduced by Java 1.4. 1) is aimed at buffers and channels, 2) contains Buffer, Channel and Selector core components, 3) supports non-blocking mode, and 4) handles concurrent connections more efficiently than traditional IO. Its advantages are reflected in: 1) Non-blocking IO reduces thread overhead, 2) Buffer improves data transmission efficiency, 3) Selector realizes multiplexing, and 4) Memory mapping speeds up file reading and writing. Note when using: 1) The flip/clear operation of the Buffer is easy to be confused, 2) Incomplete data needs to be processed manually without blocking, 3) Selector registration must be canceled in time, 4) NIO is not suitable for all scenarios.

Java's class loading mechanism is implemented through ClassLoader, and its core workflow is divided into three stages: loading, linking and initialization. During the loading phase, ClassLoader dynamically reads the bytecode of the class and creates Class objects; links include verifying the correctness of the class, allocating memory to static variables, and parsing symbol references; initialization performs static code blocks and static variable assignments. Class loading adopts the parent delegation model, and prioritizes the parent class loader to find classes, and try Bootstrap, Extension, and ApplicationClassLoader in turn to ensure that the core class library is safe and avoids duplicate loading. Developers can customize ClassLoader, such as URLClassL

The key to Java exception handling is to distinguish between checked and unchecked exceptions and use try-catch, finally and logging reasonably. 1. Checked exceptions such as IOException need to be forced to handle, which is suitable for expected external problems; 2. Unchecked exceptions such as NullPointerException are usually caused by program logic errors and are runtime errors; 3. When catching exceptions, they should be specific and clear to avoid general capture of Exception; 4. It is recommended to use try-with-resources to automatically close resources to reduce manual cleaning of code; 5. In exception handling, detailed information should be recorded in combination with log frameworks to facilitate later

HashMap implements key-value pair storage through hash tables in Java, and its core lies in quickly positioning data locations. 1. First use the hashCode() method of the key to generate a hash value and convert it into an array index through bit operations; 2. Different objects may generate the same hash value, resulting in conflicts. At this time, the node is mounted in the form of a linked list. After JDK8, the linked list is too long (default length 8) and it will be converted to a red and black tree to improve efficiency; 3. When using a custom class as a key, the equals() and hashCode() methods must be rewritten; 4. HashMap dynamically expands capacity. When the number of elements exceeds the capacity and multiplies by the load factor (default 0.75), expand and rehash; 5. HashMap is not thread-safe, and Concu should be used in multithreaded

Polymorphism is one of the core features of Java object-oriented programming. Its core lies in "one interface, multiple implementations". It implements a unified interface to handle the behavior of different objects through inheritance, method rewriting and upward transformation. 1. Polymorphism allows the parent class to refer to subclass objects, and the corresponding methods are called according to the actual object during runtime; 2. The implementation needs to meet the three conditions of inheritance relationship, method rewriting and upward transformation; 3. It is often used to uniformly handle different subclass objects, collection storage and framework design; 4. When used, only the methods defined by the parent class can be called. New methods added to subclasses need to be transformed downward and accessed, and pay attention to type safety.

Java enumerations not only represent constants, but can also encapsulate behavior, carry data, and implement interfaces. 1. Enumeration is a class used to define fixed instances, such as week and state, which is safer than strings or integers; 2. It can carry data and methods, such as passing values ??through constructors and providing access methods; 3. It can use switch to handle different logics, with clear structure; 4. It can implement interfaces or abstract methods to make differentiated behaviors of different enumeration values; 5. Pay attention to avoid abuse, hard-code comparison, dependence on ordinal values, and reasonably naming and serialization.
