Firebase
Instance ID
Deprecated
Android
Firebase Cloud Messaging

FirebaseInstanceIdService is deprecated

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Google deprecated FirebaseInstanceIdService starting with Firebase Cloud Messaging SDK version 17.0.0 (released in 2018). The token management functionality that previously lived in FirebaseInstanceIdService has been consolidated into FirebaseMessagingService. If your Android app still extends FirebaseInstanceIdService, you need to migrate to the new pattern. This article explains why the change was made, shows the old and new code side by side, and covers the migration steps.

What FirebaseInstanceIdService Did

FirebaseInstanceIdService was responsible for one primary task: receiving a callback when the FCM registration token was created or refreshed. The registration token is a unique identifier that the FCM server uses to send push notifications to a specific app instance on a specific device.

The Old Pattern

java
1// DEPRECATED - Do not use this pattern
2public class MyInstanceIdService extends FirebaseInstanceIdService {
3
4    @Override
5    public void onTokenRefresh() {
6        // Get the updated token
7        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
8        Log.d("FCM", "Refreshed token: " + refreshedToken);
9
10        // Send the token to your app server
11        sendTokenToServer(refreshedToken);
12    }
13
14    private void sendTokenToServer(String token) {
15        // POST the token to your backend API
16    }
17}

You also had to register this service in AndroidManifest.xml:

xml
1<!-- DEPRECATED - Remove this -->
2<service android:name=".MyInstanceIdService">
3    <intent-filter>
4        <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
5    </intent-filter>
6</service>

Why It Was Deprecated

Google consolidated token management into FirebaseMessagingService for several reasons:

  • Reduced complexity. Having two separate services for messaging and token management forced developers to maintain two service classes with overlapping responsibilities.
  • Simpler lifecycle. One service means one set of lifecycle callbacks to understand and debug.
  • Fewer manifest entries. Removing FirebaseInstanceIdService eliminates one service declaration and its intent filter from the manifest.
  • Better alignment with iOS. The iOS Firebase SDK already handled tokens and messages in a single delegate, so unifying Android brought the APIs closer together.

The New Pattern

After migration, FirebaseMessagingService handles both message reception and token updates.

java
1public class MyFirebaseMessagingService extends FirebaseMessagingService {
2
3    @Override
4    public void onNewToken(String token) {
5        Log.d("FCM", "New token: " + token);
6        sendTokenToServer(token);
7    }
8
9    @Override
10    public void onMessageReceived(RemoteMessage remoteMessage) {
11        // Handle incoming messages
12        if (remoteMessage.getNotification() != null) {
13            String title = remoteMessage.getNotification().getTitle();
14            String body = remoteMessage.getNotification().getBody();
15            showNotification(title, body);
16        }
17
18        // Handle data payload
19        if (remoteMessage.getData().size() > 0) {
20            Map<String, String> data = remoteMessage.getData();
21            handleDataMessage(data);
22        }
23    }
24
25    private void sendTokenToServer(String token) {
26        // POST the token to your backend API
27    }
28
29    private void showNotification(String title, String body) {
30        // Build and display a notification
31    }
32
33    private void handleDataMessage(Map<String, String> data) {
34        // Process data payload
35    }
36}

The manifest entry changes to:

xml
1<service
2    android:name=".MyFirebaseMessagingService"
3    android:exported="false">
4    <intent-filter>
5        <action android:name="com.google.firebase.MESSAGING_EVENT" />
6    </intent-filter>
7</service>

Retrieving the Token on Demand

In the old API, you called FirebaseInstanceId.getInstance().getToken() to get the current token synchronously. This method is also deprecated. The replacement uses a task-based API.

java
1// Old way (deprecated)
2String token = FirebaseInstanceId.getInstance().getToken();
3
4// New way
5FirebaseMessaging.getInstance().getToken()
6    .addOnCompleteListener(task -> {
7        if (!task.isSuccessful()) {
8            Log.w("FCM", "Token fetch failed", task.getException());
9            return;
10        }
11        String token = task.getResult();
12        Log.d("FCM", "Current token: " + token);
13        sendTokenToServer(token);
14    });

In Kotlin with coroutines, the token retrieval is even cleaner:

kotlin
1// Kotlin with coroutines
2lifecycleScope.launch {
3    try {
4        val token = FirebaseMessaging.getInstance().token.await()
5        Log.d("FCM", "Current token: $token")
6        sendTokenToServer(token)
7    } catch (e: Exception) {
8        Log.w("FCM", "Token fetch failed", e)
9    }
10}

Migration Steps

  1. Update your Firebase BOM or FCM dependency to version 17.0.0 or later in build.gradle:
groovy
1dependencies {
2    implementation platform('com.google.firebase:firebase-bom:33.1.0')
3    implementation 'com.google.firebase:firebase-messaging'
4}
  1. Move the onTokenRefresh logic from your FirebaseInstanceIdService subclass into the onNewToken method of your FirebaseMessagingService subclass.
  2. Delete the old FirebaseInstanceIdService class and remove its <service> entry from AndroidManifest.xml.
  3. Replace FirebaseInstanceId.getInstance().getToken() calls with FirebaseMessaging.getInstance().getToken() wherever you retrieve tokens on demand.
  4. Replace FirebaseInstanceId.getInstance().deleteInstanceId() with FirebaseMessaging.getInstance().deleteToken() if you need to invalidate the current token (for example, on user logout).
  5. Test token refresh by uninstalling and reinstalling the app, or by calling deleteToken() followed by getToken(). Verify that onNewToken fires and your server receives the updated token.

Common Pitfalls

  • Keeping both FirebaseInstanceIdService and FirebaseMessagingService registered in the manifest. This causes unpredictable behavior because both services can receive token events.
  • Calling the deprecated FirebaseInstanceId.getInstance().getToken() on the main thread. It can block, and on newer SDK versions it returns null and logs a warning.
  • Not handling the case where onNewToken fires before the user has logged in. You should cache the token locally and send it to your server once the user authenticates.
  • Forgetting to remove the com.google.firebase.INSTANCE_ID_EVENT intent filter from the manifest after deleting the old service.
  • Assuming onNewToken fires on every app launch. It only fires when the token actually changes. To get the current token at startup, call getToken() explicitly.

Summary

Replace FirebaseInstanceIdService with FirebaseMessagingService by moving your onTokenRefresh logic into onNewToken. Use FirebaseMessaging.getInstance().getToken() instead of the deprecated FirebaseInstanceId.getInstance().getToken() for on-demand retrieval. Remove the old service class and its manifest entry. The migration is straightforward and consolidates your FCM code into a single service.


Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.