I want to manage topic subscription from the client (android app). I am currently doing it at activity onCreate(). I am wondering if the right way is to subscribe / unsubscribe at InstanceIdService::onTokenRefresh() or at any time convenient (on button click, etc).
In short, if I manage topic subscription at the client side (no server), do I still have to bother with InstanceIdService?
Different sources of documentation provide different take on Firebase Cloud Messaging (FCM) topic subscription. Some mention InstanceIdService, some not. Here they are:
- Firebase Guide on Send Topic Messages with Firebase Console
It does not mention InstanceIdService when talking about topic subscriptions.
Once you've completed the setup tasks, you can add client code to subscribe to a topic and then handle messages sent to the topic.
Client apps can subscribe to any existing topic, or they can create a new topic. When a client app subscribes to a new topic name (one that does not already exist for your Firebase project), a new topic of that name is created in FCM and any client can subsequently subscribe to it.
To subscribe to a topic, the client app calls Firebase Cloud Messaging subscribeToTopic() with the FCM topic name:
FirebaseMessaging.getInstance().subscribeToTopic("news");
The class MyFirebaseInstanceIdService will be a service used to handle FCM logic. This service is used to alert the application when a new InstanceID token is generated, and to retrieve the generated token.
Modify it to extend FirebaseInstanceIdService and override the onTokenRefresh method to subscribe to a topic. Use the following code to update the onTokenRefresh method in MyFirebaseInstanceIdService to look like this:
public class MyFirebaseInstanceIdService extends FirebaseInstanceIdService {
private static final String TAG = "MyFirebaseIIDService";
private static final String FRIENDLY_ENGAGE_TOPIC = "friendly_engage";
/**
* The Application's current Instance ID token is no longer valid
* and thus a new one must be requested.
*/
@Override
public void onTokenRefresh() {
// If you need to handle the generation of a token, initially or
// after a refresh this is where you should do that.
String token = FirebaseInstanceId.getInstance().getToken();
Log.d(TAG, "FCM Token: " + token);
// Once a token is generated, we subscribe to topic.
FirebaseMessaging.getInstance()
.subscribeToTopic(FRIENDLY_ENGAGE_TOPIC);
}
}
It uses InstanceIdService, but topic subscription does not happen there. It is done simply in client as part of button click in an activity:
Button subscribeButton = (Button) findViewById(R.id.subscribeButton);
subscribeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// [START subscribe_topics]
FirebaseMessaging.getInstance().subscribeToTopic("news");
// [END subscribe_topics]
// Log and toast
String msg = getString(R.string.msg_subscribed);
Log.d(TAG, msg);
Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
}
});
The comment at InstanceIdService code suggests to manager subscription onTokenRefresh()
@Override
public void onTokenRefresh() {
// Get updated InstanceID token.
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
Log.d(TAG, "Refreshed token: " + refreshedToken);
// If you want to send messages to this application instance or
// manage this apps subscriptions on the server side, send the
// Instance ID token to your app server.
sendRegistrationToServer(refreshedToken);
}
As you already know,
FirebaseInstanceId
is probably a singleton class, where you retrieve your registration token. So I think thesubscribeToTopic()
method, since only the name of the topic is passed, you can presume that it already calls an instance of theFirebaseInstanceId
itself or then just send in a request towards the FCM servers with the corresponding registration token and the topic it should be subscribed to.Long story short, I don't think it's a requirement for you to extend the
FirebaseInstanceIdService
to callsubscribeToTopic()
, however, I think it's essential because (as described in the docs) it is the:For your other inquiries.
I think doing it in
onCreate()
is okay. If you see my answer here, @FrankvanPuffelen mentioned:However, I think it's also good to add in a
subscribeToTopic()
call inonTokenRefresh()
, so that as soon as a new token is provided for the app instance, you'll immediately subscribe it accordingly.Note that behavior I'm thinking here is that when a registration token is invalidated, it's subscription is also lost and that adding
subscribeToTopic()
inonRefreshToken()
will immediately re-subscribe them for you (of course this still depends in your implementation on which topic you want to subscribe it).