Firebase云消息传递 - 如何处理注销

95

当用户登出我的应用程序并且我不再希望他接收到设备的通知时,我该如何处理这种情况。

我尝试过

FirebaseInstanceId.getInstance().deleteToken(FirebaseInstanceId.getInstance().getId(), FirebaseMessaging.INSTANCE_ID_SCOPE)

但我仍然会收到发送到我的设备的registration_id的通知。

我也确认这是应该删除的令牌:

FirebaseInstanceId.getInstance().getToken(FirebaseInstanceId.getInstance().getId(), FirebaseMessaging.INSTANCE_ID_SCOPE)

或者简单地使用FirebaseInstanceId.getInstance().getToken()).

我还尝试过FirebaseInstanceId.getInstance().deleteInstanceId(),但下一次调用FirebaseInstanceId.getInstance.getToken时会收到null(第二次尝试可行)。

我猜,在deleteInstanceId之后,我可以立即再次调用getToken(),但这看起来像是一个hack。此外,这个答案表明不应该这样做,但它提出了删除标记,显然不起作用。

那么,正确的处理方法是什么?


2
在你开始实现这些解决方案之前,一定要先查看底部的Dan Alboteanu的答案; 简而言之,大多数情况都应该在服务器端处理,而不是客户端。 - tir38
13个回答

0
对于许多通知需求简单的情况,处理注销问题可以更容易地实现。例如,在我的情况下,每个用户仅订阅两个主题:
- 全局 "alerts" 主题 - 用户特定主题,以用户的电子邮件为定义(将 "@" 替换为 "-",因为主题字符串中不允许使用 "@")
对于这种简单的场景,只需在注销时取消订阅不需要的主题即可。
Future<void> signOut() async {
  messaging.unsubscribeFromTopic(emailToTopic(_firebaseAuth.currentUser.email));
  await _firebaseAuth.signOut();
}

当然,在成功登录或注册后,只订阅主题。
Future<String> signIn({String email, String password}) async {
  try {
    await _firebaseAuth.signInWithEmailAndPassword(
        email: email, password: password);
    messaging.subscribeToTopic(emailToTopic(email));
    return "Signed in";
  } on FirebaseAuthException catch (e) {
    return e.message;
  }
}

这个解决方案很简洁而且简单,不需要在客户端和服务器端管理令牌。然而,还有一个缺点!如果用户只是卸载了应用而没有退出登录,服务器怎么知道呢?如果服务器在用户卸载后继续发送用户特定的通知,那就是一种浪费! - rehman_00001

0
下面的代码我用过它,它帮助了我,我使用了 Kotlin 协程而不是 Thread(Runnable{}).start(),因为它比创建一个新的线程对象更节省成本。
 private fun logoutFromFCM() {
    GlobalScope.launch(Dispatchers.IO) {
        FirebaseInstallations.getInstance().delete()
        FirebaseMessaging.getInstance().deleteToken()

        FirebaseMessaging.getInstance().token.addOnCompleteListener(OnCompleteListener { task ->
            if (!task.isSuccessful) {
                Log.w(TAG, "Fetching FCM registration token failed", task.exception)
                return@OnCompleteListener
            }

            // Get new FCM registration token
            val token = task.result
            saveFirebaseToken(token)
            Log.w(TAG, "Token Updated - newToken> $token")
        })
    }
}

0
总之,使用后台线程删除instanceID,下次登录时请注意Firestore/Realtime DB(如果您将令牌保存在那里),它们将会刷新。
public void Logout() {

        new Thread(){
            @Override
            public void run() {
                super.run();
                try {
                    FirebaseInstanceId.getInstance().deleteInstanceId();
                    FirebaseInstanceId.getInstance().getInstanceId();
                } catch (final IOException e) {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(Flags.this, e.getMessage(), Toast.LENGTH_SHORT).show();
                        }
                    });
                }
            }
        }.start();
        FirebaseMessaging.getInstance().setAutoInitEnabled(false);
        FirebaseAuth.getInstance().signOut();
        SharedPreferences sharedPreferences = getDefaultSharedPreferences(Flags.this);
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.clear();
        editor.apply();
        startActivity(new Intent(Flags.this, MainActivity.class));
        Flags.this.finish();
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接