Keywords: FCM Token | Firebase Cloud Messaging | Android Push Notifications | Token Management | Message Delivery Optimization
Abstract: This article provides an in-depth analysis of FCM tokens in Firebase Cloud Messaging, detailing the evolution of token retrieval methods on Android platforms from traditional FirebaseInstanceIdService.onTokenRefresh() to modern FirebaseMessagingService.onNewToken(). Combined with best practices, it explores effective token lifecycle management including token storage, periodic updates, expiration detection, and invalid token cleanup, helping developers build stable and efficient push notification systems.
Core Concepts of FCM Tokens
FCM Token (Firebase Cloud Messaging Token), commonly referred to as registrationToken in official documentation, is a unique identifier issued by GCM connection servers to client applications. This token enables applications to receive message pushes from FCM servers. It is crucial to note that registration tokens are sensitive information and must be properly secured against leakage.
Evolution of Token Retrieval Mechanisms
The method of obtaining tokens has undergone significant evolution throughout FCM's development. Early versions primarily handled token updates through the FirebaseInstanceIdService.onTokenRefresh() method:
@Override
public void onTokenRefresh() {
// Get updated InstanceID token
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
Log.d(TAG, "Refreshed token: " + refreshedToken);
// Implement logic to send registration to your app's servers
sendRegistrationToServer(refreshedToken);
}
With updated FCM versions, it is now recommended to use the FirebaseMessagingService.onNewToken() method as a replacement for the old implementation. Based on practical experience, the new method maintains functionality similar to the original onTokenRefresh() but offers a more architecturally sound approach.
Token Lifecycle Management
During the initial startup of an application, the FCM SDK automatically generates a registration token for the client app instance. This token is essential for implementing targeted device pushes or creating device groups. Developers can access the token value by extending the appropriate service classes, but must ensure proper service configuration in the manifest file.
The onTokenRefresh callback automatically triggers when a new token is generated. Calling the getToken method within this context ensures retrieval of the current available registration token. It is important to note that FirebaseInstanceID.getToken() returns null if the token has not yet been generated.
Server-Side Token Storage Strategies
After obtaining the token, it should be immediately sent to the application server and stored securely. A critical responsibility of the server is to maintain token information for each client and keep the active token list updated in real-time. Strongly recommended is the implementation of a token timestamp mechanism in both code and server-side, with regular updates to this timestamp.
Below is a Kotlin example using Cloud Firestore to store tokens and timestamps:
private fun sendTokenToServer(token: String?) {
val deviceToken = hashMapOf(
"token" to token,
"timestamp" to FieldValue.serverTimestamp(),
)
Firebase.firestore.collection("fcmTokens").document("myuserid")
.set(deviceToken)
}
override fun onNewToken(token: String) {
Log.d(TAG, "Refreshed token: $token")
sendTokenToServer(token)
}
Token Freshness Maintenance Mechanisms
Stale registration tokens are those associated with inactive devices that have not connected to FCM for over a month. As time progresses, the likelihood of these devices reconnecting to FCM diminishes significantly. For Android devices, when stale tokens reach 270 days of inactivity, FCM considers them expired. Once a token expires, FCM marks it as invalid and rejects message sends to it.
To ensure accurate message delivery, the following measures are recommended:
- Periodically retrieve and update all registration tokens on the server
- Implement monthly token update frequency to balance battery impact and detection of inactive registration tokens
- Monitor invalid token responses from the FCM backend and promptly remove them from the system
Invalid Token Detection and Cleanup
Through the HTTP v1 API, the following error messages may indicate that send requests are targeting invalid or expired tokens: UNREGISTERED (HTTP 404) and INVALID_ARGUMENT (HTTP 400). If the message payload is confirmed valid but these responses are still received, it is safe to delete the token record.
Here is an example using Cloud Functions to clean up stale tokens:
exports.pruneTokens = functions.pubsub.schedule('every 24 hours').onRun(async (context) => {
const staleTokensResult = await admin.firestore().collection('fcmTokens')
.where("timestamp", "<", Date.now() - EXPIRATION_TIME)
.get();
staleTokensResult.forEach(function(doc) { doc.ref.delete(); });
});
Topic Subscription Management Optimization
For scenarios utilizing topic functionality, it is recommended to resubscribe to topics monthly and perform subscription operations when registration tokens change. This self-healing solution ensures that subscription relationships automatically restore when applications become active again. Additionally, for application instances idle for over a month, the token-to-topic mapping should be deleted from the FCM backend using Firebase Admin SDK.
Delivery Success Rate Measurement
To obtain the most accurate message delivery data, it is optimal to send messages only to actively used application instances. Before targeting messages to a token, consider the following factors: whether Google Analytics data, data captured in BigQuery, or other tracking signals indicate the token is active; whether previous delivery attempts have consistently failed over a period of time; whether the registration token has been updated on servers within the past month.