Firebase云消息传递 – 处理注销

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

我试过了

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之后,我可以立即再次调用deleteInstanceId getToken() ,但它看起来像是一个黑客。 并且还有这个答案表明不应该这样做,但它建议删除显然不起作用的令牌。

那么处理这个问题的正确方法是什么?

Solutions Collecting From Web of "Firebase云消息传递 – 处理注销"

好的。 所以我设法做了一些测试并得出以下结论:

  1. deleteToken()deleteToken() getToken(String, String)的对应物,但不是deleteToken()的对应物。

只有在您传递的发件人ID是不同的发件人ID(与您在google-services.json中可以看到的ID不同)时,它才有效。 例如,您希望允许其他服务器发送到您的应用,您可以调用getToken("THEIR_SENDER_ID", "FCM")来授予他们发送到您应用的权限。 这将返回一个不同的注册令牌,该令牌仅对应于该特定发件人。

将来,如果您选择删除授权发送到您的应用程序,则必须使用deleteToken("THEIR_SENDER_ID", "FCM") 。 这将使相应的令牌无效,并且当发件人尝试发送消息时,作为预期的行为,他们将收到NotRegistered错误。

  1. 要删除您自己的发件人的令牌,正确的处理方法是使用deleteInstanceId()

特别提到@Prince的这个答案 ,特别是帮助我解决这个问题的代码示例。

正如@MichałK已经在他的post中所做的那样,在调用deleteInstanceId() ,应该调用deleteInstanceId()以发送对新令牌的请求。 但是,您不必第二次调用它。 只要实现onTokenRefresh() ,它就会自动触发为您提供新令牌。

简而言之, deleteInstanceId() > deleteInstanceId() >检查onTokenRefresh()

注意 :调用deleteInstanceId()不仅会删除您自己的应用程序的令牌。 它将删除所有主题订阅以及与应用实例关联的所有其他令牌。


你肯定是在正确地调用deleteToken()吗? 观众的价值应该(也可以从我链接的答案中看出)“设置为应用服务器的发件人ID”。 您传递的getId()值与发件人ID(它包含应用程序实例ID值)不同。 另外,您如何发送消息(App Server或Notifications Console)?

getToken()getToken(String, String)返回不同的标记。 在这里看到我的答案。

我也尝试过FirebaseInstanceId.getInstance().deleteInstanceId() ,但是下次我调用FirebaseInstanceId.getInstance.getToken我收到null(它在第二次尝试时有效)。

这可能是因为你第一次调用getToken() ,它仍然在生成。 这只是预期的行为。

我想,在deleteInstanceId之后,我可以立即再次调用deleteInstanceId getToken() ,但它看起来像是一个黑客。

不是真的。 这就是你如何获得新生成的(如果它已经生成)令牌。 所以我认为没关系。

尝试这个

当我从我的应用程序注销时,我正在处理同样的情况,但问题是在注销后我仍然从firebase获取推送通知。所以尝试删除 firebase 令牌但是在注销方法中删除令牌时该应用程序以登录方式进入,当尝试获取friebase令牌时显示为NULL ,因此我的应用程序在删除firebase令牌后崩溃。工作2天后我终于获得了我的解决方案..希望这对您也有用。

  1. 在您的注销方法中删除后台中的firebase令牌,因为您无法在main方法中删除firebase令牌

     new AsyncTask() { @Override protected Void doInBackground(Void... params) { { try { FirebaseInstanceId.getInstance().deleteInstanceId(); } catch (IOException e) { e.printStackTrace(); } } return null; } @Override protected void onPostExecute(Void result) { //call your activity where you want to land after log out } }.execute(); 
  2. 在您的登录方法活动中再次生成firebase令牌(首选onresume方法)

     new AsyncTask() { @Override protected Void doInBackground(Void... params) { String token = FirebaseInstanceId.getInstance().getToken(); while(token == null)//this is used to get firebase token until its null so it will save you from null pointer exeption { token = FirebaseInstanceId.getInstance().getToken(); } return null; } @Override protected void onPostExecute(Void result) { } }.execute(); 

在我的情况下,如果没有评论我的问题,它对我有用

我做了一个简短的研究,讨论如何恢复完全控制(订阅和取消订阅FCM)的最优雅的解决方案。 用户登录或注销后启用和禁用FCM。

步骤1. – 防止自动初始化

Firebase现在处理InstanceID以及需要生成注册令牌的所有其他内容。 首先,您需要阻止自动初始化 。 根据官方设置文档,您需要将这些元数据值添加到AndroidManifest.xml

 < ?xml version="1.0" encoding="utf-8"?>            

现在您禁用了自动令牌请求过程。 同时,您可以选择在运行时通过代码再次启用它。

步骤2. – 实现enableFCM()enableFCM() disableFCM()函数

如果再次启用自动初始化,则会立即收到新令牌,因此这是实现enableFCM()方法的完美方法。 所有订阅信息都分配给InstanceID,因此当您删除它时,然后启动取消订阅所有主题。 通过这种方式,您可以实现disableFCM()方法,只需在删除之前关闭自动初始化。

 public class FCMHandler { public void enableFCM(){ // Enable FCM via enable Auto-init service which generate new token and receive in FCMService FirebaseMessaging.getInstance().setAutoInitEnabled(true); } public void disableFCM(){ // Disable auto init FirebaseMessaging.getInstance().setAutoInitEnabled(false); new Thread(() -> { try { // Remove InstanceID initiate to unsubscribe all topic // TODO: May be a better way to use FirebaseMessaging.getInstance().unsubscribeFromTopic() FirebaseInstanceId.getInstance().deleteInstanceId(); } catch (IOException e) { e.printStackTrace(); } }).start(); } } 

步骤3. – FCMService实现 – 令牌和消息接收

在最后一步中,您需要接收新令牌并直接发送到您的服务器。 另一方面,您将收到您的数据信息,并按照您的要求进行操作。

 public class FCMService extends FirebaseMessagingService { @Override public void onNewToken(String token) { super.onNewToken(token); // TODO: send your new token to the server } @Override public void onMessageReceived(RemoteMessage remoteMessage) { super.onMessageReceived(remoteMessage); String from = remoteMessage.getFrom(); Map data = remoteMessage.getData(); if (data != null) { // TODO: handle your message and data sendMessageNotification(message, messageId); } } private void sendMessageNotification(String msg, long messageId) { // TODO: show notification using NotificationCompat } } 

我认为这个解决方案清晰,简单,透明。 我在生产环境中进行了测试,但它确实有效。 我希望它有所帮助。

我知道我迟到了。 应该从后台线程调用deleteInstanceId()因为它是一个阻塞调用。 只需检查FirebaseInstanceId()类中的方法deleteInstanceId()

 @WorkerThread public void deleteInstanceId() throws IOException { if (Looper.getMainLooper() == Looper.myLooper()) { throw new IOException("MAIN_THREAD"); } else { String var1 = zzh(); this.zza(this.zzal.deleteInstanceId(var1)); this.zzl(); } } 

您可以启动IntentService来删除实例ID以及与之关联的数据。