我做了一个简短的研究,研究什么是最优雅的解决方案,可以像以前一样重新获得完全控制(订阅和取消订阅 FCM)。在用户登录或注销后启用和禁用 FCM。
第 1 步 - 防止自动初始化
Firebase 现在可以处理 InstanceID 以及需要生成注册令牌的所有其他内容。首先你需要防止自动初始化。根据official set-up documentation,您需要将这些元数据值添加到您的AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<application>
<!-- FCM: Disable auto-init -->
<meta-data android:name="firebase_messaging_auto_init_enabled"
android:value="false" />
<meta-data android:name="firebase_analytics_collection_enabled"
android:value="false" />
<!-- FCM: Receive token and messages -->
<service android:name=".FCMService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
</application>
现在您禁用了自动令牌请求过程。同时,您可以选择在运行时通过代码再次启用它。
第 2 步 - 实现 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
}
}
我认为这个解决方案是清晰、简单和透明的。我在生产环境中进行了测试,并且可以正常工作。希望对您有所帮助。