Push Notifications
Send push notifications via Firebase Cloud Messaging. Set up FCM, create notification channels, build notifications with actions, and handle foreground vs background delivery.
Push Notifications is a free Android Academy lesson on CoddyKit — lesson 4 of 6. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Android Academy learning path, one of 6 lessons in the course, and your progress syncs across the web and the CoddyKit app.
What Are Push Notifications?
Push notifications let your server send messages to users even when the app is not in the foreground. Common uses:
- New message alerts
- Order status updates
- Breaking news
- Reminders and promotions
On Android, Firebase Cloud Messaging (FCM) is the standard push delivery service.
FCM Overview
Firebase Cloud Messaging (FCM) flow:
- App registers with FCM on first launch → receives a device token
- App sends the token to your server
- When you want to push, your server sends a message to FCM
- FCM delivers it to the device
FCM is free, reliable, and works even when the app is killed.
Adding Firebase to the Project
Steps to add Firebase:
- Go to Firebase Console → Add project → Add Android app
- Register your app with the package name
- Download
google-services.jsonand place it inapp/ - Add plugins and dependencies
// project/build.gradle:
buildscript {
dependencies { classpath 'com.google.gms:google-services:4.4.1' }
}
// app/build.gradle:
plugins { id 'com.google.gms.google-services' }
dependencies {
implementation platform('com.google.firebase:firebase-bom:32.7.4')
implementation 'com.google.firebase:firebase-messaging-ktx'
}FCM Permission (Android 13+)
Starting with Android 13 (API 33), you must request the POST_NOTIFICATIONS permission at runtime — just like a dangerous permission:
<!-- AndroidManifest.xml -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
// In Activity (Android 13+):
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
requestPermissionLauncher.launch(android.Manifest.permission.POST_NOTIFICATIONS)
}FirebaseMessagingService
Create a service that handles incoming FCM messages and token refreshes:
class MyFirebaseService : FirebaseMessagingService() {
override fun onNewToken(token: String) {
// Send token to your backend to enable push delivery
sendTokenToServer(token)
}
override fun onMessageReceived(message: RemoteMessage) {
val title = message.notification?.title ?: "New Message"
val body = message.notification?.body ?: ""
showNotification(title, body)
}
}Register Service in Manifest
Declare the service in AndroidManifest.xml:
<service
android:name=".MyFirebaseService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>Notification Channels (Android 8+)
Since Android 8 (Oreo), notifications must be assigned to a channel. Users can control sound, vibration, and importance per channel:
fun createNotificationChannel(context: Context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
"messages_channel", // channel ID
"Messages", // user-visible name
NotificationManager.IMPORTANCE_HIGH
).apply {
description = "Incoming message notifications"
enableVibration(true)
}
val manager = context.getSystemService(NotificationManager::class.java)
manager.createNotificationChannel(channel)
}
}Building & Showing a Notification
Use NotificationCompat.Builder for compatibility across Android versions:
fun showNotification(context: Context, title: String, body: String) {
val intent = Intent(context, MainActivity::class.java)
val pendingIntent = PendingIntent.getActivity(
context, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
val notification = NotificationCompat.Builder(context, "messages_channel")
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle(title)
.setContentText(body)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true) // dismiss on tap
.setContentIntent(pendingIntent) // open app on tap
.build()
NotificationManagerCompat.from(context)
.notify(System.currentTimeMillis().toInt(), notification)
}Notification with Actions
Add action buttons to notifications so users can act without opening the app:
val replyIntent = Intent(context, ReplyReceiver::class.java)
val replyPending = PendingIntent.getBroadcast(
context, 1, replyIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
val notification = NotificationCompat.Builder(context, "messages_channel")
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle("New message from Alice")
.setContentText("Hey, are you coming?")
.addAction(R.drawable.ic_reply, "Reply", replyPending)
.addAction(R.drawable.ic_dismiss, "Dismiss", null)
.build()Foreground vs Background Handling
FCM behaves differently depending on app state:
- App in foreground —
onMessageReceived()is called; you build and show the notification yourself - App in background/killed — FCM automatically shows the notification from the
notificationpayload;onMessageReceivedis NOT called
Put extra data in the data payload (not notification) to always receive it in onMessageReceived.
Getting the FCM Token
Retrieve the current FCM token to send to your server:
FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->
if (!task.isSuccessful) {
Log.w("FCM", "Fetching token failed", task.exception)
return@addOnCompleteListener
}
val token = task.result
Log.d("FCM", "Token: $token")
// Send token to your server
sendTokenToServer(token)
}Quick Check
What happens when your app is in the background and FCM delivers a message with a 'notification' payload?
Recap: Push Notifications
Push notifications with FCM on Android:
- Add Firebase,
google-services.json, andfirebase-messaging-ktx - Request
POST_NOTIFICATIONSon Android 13+ - Create
FirebaseMessagingService→onNewToken+onMessageReceived - Create a
NotificationChannelfor Android 8+ - Build notifications with
NotificationCompat.Builder - Use data payload to always receive in
onMessageReceived
Next: schedule background work with WorkManager.
Frequently asked questions
Is the “Push Notifications” lesson free?
Yes — the full text of “Push Notifications” is free to read here on the web, and the Android Academy course includes 6 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Android Academy course, upgrade to CoddyKit PRO.
What will I learn in “Push Notifications”?
Send push notifications via Firebase Cloud Messaging. Set up FCM, create notification channels, build notifications with actions, and handle foreground vs background delivery. You practise Android Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Android Academy?
No prior experience is required. Android Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 6, so you can start here or from the beginning and move at your own pace.
How long does the “Push Notifications” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Android Academy lesson?
Yes. Every Android Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.