Lennon Spirlandelli
Lennon Spirlandelli

Reputation: 3193

Unsubscribe from all topics at once from Firebase Messaging

Is there any way to unsubscribe from all topics at once?

I'm using Firebase Messaging to receive push notification from some topics subscribed, and somehow I need to unsubscribe from all topics without unsubscribing one by one. Is that possible?

Upvotes: 45

Views: 46497

Answers (9)

Valentin Yuryev
Valentin Yuryev

Reputation: 814

Firebase.messaging.deleteToken()

Is actual answer for 2021.

Upvotes: 3

Rahul Repala
Rahul Repala

Reputation: 109

if you are using flutter if you want to unsubscribe from all topics use-

  final FirebaseMessaging _fcm = FirebaseMessaging();
  _fcm.deleteInstanceID().then((value){
                print('deleted all'+value.toString());
              });

Upvotes: 0

Saravanan M
Saravanan M

Reputation: 1

try {
    FirebaseInstallations.getInstance().delete()
} catch (e: IOException) {

}

Upvotes: -2

Jeff Gu Kang
Jeff Gu Kang

Reputation: 4869

We can use the unsubcribeAllTopics in server side as below.

Example,

interface GetTopics {
  rel: {topics: {[key: string]: any}}
}

/**
 * Unsubcribe all topics except one topic
 * 
 * Example response of `https://iid.googleapis.com/iid/info/${fcmToken}?details=true`
 * {
    "applicationVersion": "...",
    "application": "...",
    "scope": "*",
    "authorizedEntity": "...",
    "rel": {
        "topics": {
            "TOPIC_KEY_STRING": { // topic key
                "addDate": "2020-12-23"
            }
        }
    },
    "appSigner": "...",
    "platform": "ANDROID"
}
 */
export const unsubcribeAllTopics = async (
  fcmTokens: string | string[],
  exceptTopic?: string,
) => {
  const headers = {
    'Content-Type': 'application/json',
    Authorization: `key=${process.env.FCM_SERVER_KEY}`,
  }

  const url = `https://iid.googleapis.com/iid/info/${fcmTokens}?details=true`

  try {
    const response = await fetch(url, {method: 'GET', headers: headers})
    const result: GetTopics = await response.json()
    const keys = Object.keys(result.rel.topics)

    keys.forEach(key => {
      key !== exceptTopic &&
        messaging()
          .unsubscribeFromTopic(fcmTokens, key)
          .catch(error => {
            console.error('error', {data: error})
          })
    })
  } catch (error) {
    console.error('error', {data: error})
  }
}

https://gist.github.com/JeffGuKang/62c280356b5632ccbb6cf146e2bc4b9d

Upvotes: 0

Mutlu Simsek
Mutlu Simsek

Reputation: 1172

If you want to avoid deleting InstanceId and moreover, to avoid missing some of the subscribed topics when saved in a local database or a remote database due to highly probable buggy implementation.

First get all subscribed topics:

    var options = BaseOptions(headers: {'Authorization':'key = YOUR_KEY'});
    var dio = Dio(options);
    var response = await dio.get('https://iid.googleapis.com/iid/info/' + token,
                             queryParameters: {'details': true});
    Map<String, dynamic> subscribedTopics = response.data['rel']['topics'];

Get your key here: Firebase console -> your project -> project settings -> cloud messaging -> server key

Get your token as:

var firebaseMessaging = FirebaseMessaging();
String token;
firebaseMessaging.getToken().then((value) {
  token = value;
});

Now unsubscribe from all topics:

  Future<void> unsubscribeFromAllTopics() async {
    for (var entry in subscribedTopics.entries) {
      await Future.delayed(Duration(milliseconds: 100)); // throttle due to 3000 QPS limit
      unawaited(firebaseMessaging.unsubscribeFromTopic(entry.key)); // import pedantic for unawaited
      debugPrint('Unsubscribed from: ' + entry.key);
    }
  }

All code is in Dart.

For more information about instance id: https://developers.google.com/instance-id/reference/server

Upvotes: 5

Blasanka
Blasanka

Reputation: 22417

For Java users:

If you want to do it topic wise, refer others answers and If you want to stop recieving FCM push notification, do below:

new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            FirebaseInstanceId.getInstance().deleteInstanceId();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}).start();

I have placed deleteInstanceId() in a separate thread to stop java.io.IOException: MAIN_THREAD W/System.err and wrapped with try / catch to handle IOException.

Upvotes: 2

Jacob Nordfalk
Jacob Nordfalk

Reputation: 3533

Keep a private list of subscribed topics in Preferences.

It's not that hard. Here's what I do:

public class PushMessagingSubscription {

  private static SharedPreferences topics;

  public static void init(ApplicationSingleton applicationSingleton) {
    topics = applicationSingleton.getSharedPreferences("pushMessagingSubscription", 0);
  }

  public static void subscribeTopic(String topic) {
    if (topics.contains(topic)) return; // Don't re-subscribe
    topics.edit().putBoolean(topic, true).apply();

    // Go on and subscribe ...
  }


  public static void unsubscribeAllTopics() {
    for (String topic : topics.getAll().keySet()) {
      FirebaseMessaging.getInstance().unsubscribeFromTopic(topic);
    }
    topics.edit().clear().apply();
    // FirebaseInstanceId.getInstance().deleteInstanceId();
  }
}

Upvotes: 2

kirtan403
kirtan403

Reputation: 7411

You can use Instance API to query all the available topics subscribed to given token and than call multiple request to unsubscribe from all the topics.

However, if you want to stop receiving from all the topics and then the token is not useful at all, you can call FirebaseInstanceId.getInstance().deleteInstanceId() (reference: deleteInstanceId() and surround with a try/catch for a potential IOException) that will reset the instance id and than again you can subscribe to new topics from the new instance id and token.

Hope this helps someone.

Upvotes: 22

Mirza Asad
Mirza Asad

Reputation: 606

I know this is not the best way but it works! You can store list of all topics in Database and then unsubscribe from all topics when user sign-outs

final FirebaseMessaging messaging= FirebaseMessaging.getInstance();
      FirebaseDatabase.getInstance().getReference().child("topics").addChildEventListener(new ChildEventListener() {
          @Override
          public void onChildAdded(DataSnapshot dataSnapshot, String s) {
              String topic  = dataSnapshot.getValue(String.class);
              messaging.unsubscribeFromTopic(topic);
}...//rest code

Upvotes: 3

Related Questions