Firebase FCM Token — Complete Guide
In this tutorial, you'll learn about Firebase FCM Token. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
The Problem
Your FCM token is empty, or you send a notification to the stored token and it doesn't arrive because the token was refreshed.
Wrong Approach ❌
// Getting token on main thread — may be delayed
val token = FirebaseMessaging.getInstance().token // Not yet available!
// Storing token once at app startup
override fun onCreate() {
super.onCreate()
FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->
val token = task.result
saveTokenToServer(token) // Token stored once — never updated!
}
}
Output: Token is null or stale. Notifications fail silently.
Right Approach ✅
// FCM Service to handle token
class MyFcmService : FirebaseMessagingService() {
// Called when a new token is generated (initial + refresh)
override fun onNewToken(token: String) {
super.onNewToken(token)
sendTokenToServer(token)
saveTokenLocally(token)
}
private fun sendTokenToServer(token: String) {
// Use coroutine for network call
CoroutineScope(Dispatchers.IO).launch {
try {
api.registerDeviceToken(token)
} catch (e: Exception) {
// Retry on next app launch
scheduleTokenRetry(token)
}
}
}
}
// In Application class — retrieve existing token
class App : Application() {
override fun onCreate() {
super.onCreate()
// Retrieve current token (may be null if not yet generated)
FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->
if (task.isSuccessful) {
val token = task.result
Log.d("FCM", "Token: $token")
}
}
// Alternative: blocking suspend call in a coroutine
CoroutineScope(Dispatchers.IO).launch {
val token = FirebaseMessaging.getInstance().token.await()
Log.d("FCM", "Token: $token")
}
}
}
// Special handling for Firebase on Android
// Ensure google-services.json is in app/ folder and FCM dependency is added
Output: Token always available and synced to server.
Prevention
- Implement
FirebaseMessagingService.onNewToken()for token refresh. - Store token locally and sync to server on every change.
- Use
.await()fromkotlinx.coroutines.tasks.awaitfor clean Coroutine usage. - Retry token upload if server is unreachable.
Common Mistakes with Firebase fcm token
- Forgetting that lazy evaluation defers computation until the value is forced, causing space leaks with unevaluated thunks
- Using
returnto exit a function early instead of wrapping a pure value in the monad - Mixing let bindings with <- bindings in do notation, producing type errors
These mistakes appear frequently in real-world Android code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.
Practice Exercise
Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.
This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.
FAQ
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro