35

According to Firebase cloud messaging documentation, for subscribing a user to a topic I need to call

FirebaseMessaging.getInstance().subscribeToTopic("news");
  1. In my application, I need all users to be subscribed to my cloud messaging topic. Since return value is void, the question is how can I understand that subscription was successful?
  2. Is it a bad practice to call subscribeToTopic each time my application starts?
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
VSB
  • 9,825
  • 16
  • 72
  • 145

2 Answers2

37

1. How can I understand that subscription was successful?

Edit:

You could now check if subscription is successful by adding addOnSuccessListener()

FirebaseMessaging.getInstance().subscribeToTopic("news").addOnSuccessListener(new OnSuccessListener<Void>() {
        @Override
        public void onSuccess(Void aVoid) {
            Toast.makeText(getApplicationContext(),"Success",Toast.LENGTH_LONG).show();
        }
    });

Original:

There is nothing explicitly mentioned in the docs about a response received when the subscription is successful.

However, if you need to mandate all of your users to be subscribed to a specific topic, you should call the subscribeToTopic on your app's first install. This will most likely make sure that there is a connection to the internet (since it's probably been downloaded and installed via the Play Store) and the subscription successful.

However, if you want to make sure, you can also handle he checking via your own App Server. As mentioned in the docs:

You can take advantage of Instance ID APIs to perform basic topic management tasks from the server side. Given the registration token(s) of client app instances, you can do the following:

Check through the registration tokens, if they haven't been successfully subsribed to your topic, send a notification to it where it will trigger your client app to call subscribeToTopic.

2. Is it a bad practice to call subscribeToTopic each time my application starts?

Edit: Adding it in from the comments section: Subscribing on app start should be fine.

Thank you @FrankvanPuffelen for verifying. :)

Community
  • 1
  • 1
AL.
  • 36,815
  • 10
  • 142
  • 281
  • 4
    2) nope, subscribing to topics on app start is fine. – Frank van Puffelen Oct 15 '16 at 05:45
  • 1
    @FrankvanPuffelen and another question? Do `subscribeToTopic` will retry on background to be submitted by google services or such thing (if internet connection was not available at time of instruction execution)? – VSB Oct 15 '16 at 12:59
  • 3
    @VSB: `subscribeToTopic` will keep retry on background, but it's tied to your app lifecycle (not to google services, yet). So if your app is killed it will stop retrying until the app is open again. (the action is stored so it will be resumed when the app is started again) – Diego Giorgini Oct 23 '16 at 18:07
  • @DiegoGiorgini - Thanks for that info. VSB actually made a separate post for that question and I provided an [answer](http://stackoverflow.com/a/40109977/4625829), which I edited, adding in your comment. I just have one question, is there any instance at all where the retry stops without actually completing? A clear cache perhaps? – AL. Oct 24 '16 at 10:20
  • 3
    retry stops working forever only if the user deletes the app data. (not the cache, that is not important). Please note that deleting the app data is the same as uninstalling and reinstalling and this applies to any other library or feature. Not only to FCM. – Diego Giorgini Oct 25 '16 at 05:09
  • @DiegoGiorgini Thanks for your useful information. However I want to know is this behavior is documented somewhere or you know that by experience? – VSB Oct 25 '16 at 05:25
  • 9
    I am a Google developer in the FCM team. You are right that subscribeToTopic is not documented as clearly as I described here. I will look into adding full documentation in the javadoc for one of the future releases. – Diego Giorgini Oct 25 '16 at 05:39
  • @DiegoGiorgini Thank you so much for the details. :) – AL. Oct 25 '16 at 06:01
  • 1
    @Diego Could it be that `subscribeToTopic()` also stops trying after 20-30 seconds and then the device remains unsubscribed? Your [reply](http://stackoverflow.com/questions/40055051/android-subscribe-to-firebase-cloud-messagingfcm-topic/40055267#comment67726207_40055267) to AL does not address that eventuality. – Richard Le Mesurier Feb 23 '17 at 10:12
  • 2
    subscribeToTopic() will NOT stop retrying. but it's smart enough to detect if the device is offline, and if so it will not retry until the device is back online. But as I wrote above this logic is contained in the app code, so if the app is killed by Android (low resources, doze mode, etc) then the retry logic could be stopped/delayed until the app is open again by the user. – Diego Giorgini Feb 23 '17 at 10:46
  • Is it really necessary to call subscribeToTopic() every time app starts? It's not clear to me if topic subscription should be executed once (at onTokenRefresh for example) or repeatedly (when app starts for example). – Cleyton T. Jan 26 '18 at 19:35
  • 4
    @CleytonT. It's not technically *necessary*. It may depend on your use case. For example, if you want a global topic where all users are a member of, you'd have to make sure that they are subscribed to it. Putting the subscribe method when the app starts guarantees this. Putting the subscribe in `onTokenRefresh` is unnecessary since when a token is *refreshed*, their corresponding topic subscriptions are carried over. – AL. Jan 27 '18 at 04:24
  • Got it. Thanks @AL. – Cleyton T. Jan 28 '18 at 11:20
  • @AL., Regarding 2) I do receive messages for registered topic, but `OnSuccessListener` (along with `OnFailureListener`, `CompleteListener`) is never being called, which is sad, since I would like to know was the subscription successful or not. – Alexander Skvortsov Aug 15 '18 at 14:10
  • @AlexanderSkvortsov It's hard to comment on what the issue might be without seeing any code. However, what you described seems like a real issue. The purpose of the listeners was to detect results for the task of subscribing. If it fails to do that only task, then it could be a bug. I suggest posting a question here so the community could help figure it out. Cheers! – AL. Aug 15 '18 at 17:12
  • @AL, I have started another topic regarding that here: https://stackoverflow.com/q/51860522/3090951, There are some code :-) – Alexander Skvortsov Aug 16 '18 at 09:22
  • @AlexanderSkvortsov Went to your post and saw Doug's comment suggesting that you file a bug. With his background on Firebase, I strongly advise that you follow it. Good luck! – AL. Aug 16 '18 at 10:30
  • 3
    @DiegoGiorgini Can anyone comment about if a user is already subscribed to a topic how FCM/Firebase handles to trying to subscribe the same user to the same topic again? – rolinger Jun 11 '19 at 16:57
4

I have written this function and tested. May be helpful.

    private void subscribeToMessaging(){
        SharedPreferences prefs = getSharedPreferences(SETTINGS_TITLE, MODE_PRIVATE);

// Getting value from shared preferences
        boolean isSubscriptionEnable = prefs.getBoolean(SETTING_NOTIFICATION, true);

// if "isSubscriptionEnable" is true then check whether its already subscribed or not
        if (isSubscriptionEnable){

            boolean alreadySubscribed = prefs.getBoolean(SETTING_ALREADY_SUBSCRIBED, false);
// if not already subscribed then subscribe to topic and save value to shared preferences
            if (!alreadySubscribed){
                FirebaseMessaging.getInstance().subscribeToTopic("global").addOnSuccessListener(new OnSuccessListener<Void>() {
        @Override
        public void onSuccess(Void aVoid) {
            Toast.makeText(getApplicationContext(),"Success",Toast.LENGTH_LONG).show();
        }
    });

                SharedPreferences.Editor editor = getSharedPreferences(SETTINGS_TITLE, MODE_PRIVATE).edit();
                editor.putBoolean(SETTING_ALREADY_SUBSCRIBED, true);
                editor.apply();
                Toast.makeText(this, "Subscribed", Toast.LENGTH_LONG).show();
            } else {
                Toast.makeText(this, "Already subscribed", Toast.LENGTH_LONG).show();
            }
        }
    }

Don't forget to write these lines above onCreate()

    public static final String SETTINGS_TITLE = "settings";
    public static final String SETTING_NOTIFICATION = "notification_state";
    public static final String SETTING_ALREADY_SUBSCRIBED = "already_subscribed";
Pooja
  • 475
  • 5
  • 14
  • 1
    Sometimes the subscribeToTopic may result in failure. – Sai Sep 24 '19 at 13:02
  • 1
    @Sai I have added `addOnSuccessListener` for confirm that subscription success or not. I hope it will be helpful. – Pooja Nov 13 '19 at 06:13