Reputation: 3193
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
Reputation: 814
Firebase.messaging.deleteToken()
Is actual answer for 2021.
Upvotes: 3
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
Reputation: 1
try {
FirebaseInstallations.getInstance().delete()
} catch (e: IOException) {
}
Upvotes: -2
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
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
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
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
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
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