如何配置Firebase Messaging仅向已登录用户发送通知?
嘿,我之前也踩过这个坑!其实核心逻辑就是把FCM令牌的注册与用户登录状态绑定——只有当用户成功登录后,才把设备的FCM令牌和用户账号关联起来,发送通知时只针对这些已绑定的令牌推送就行。下面是具体的实现步骤:
解决思路与代码实现
1. 延迟FCM令牌的获取与上传
默认FCM会在应用启动时自动生成令牌,但我们要把这个动作延后到用户登录成功之后:
// 在用户登录成功的回调中执行令牌获取与绑定 FirebaseAuth.getInstance().signInWithEmailAndPassword(email, password) .addOnCompleteListener(task -> { if (task.isSuccessful()) { FirebaseUser currentUser = FirebaseAuth.getInstance().getCurrentUser(); if (currentUser == null) return; // 用户登录成功,获取FCM令牌 FirebaseMessaging.getInstance().getToken() .addOnCompleteListener(tokenTask -> { if (!tokenTask.isSuccessful()) { Log.w(TAG, "获取FCM令牌失败", tokenTask.getException()); return; } String fcmToken = tokenTask.getResult(); // 将令牌与用户UID绑定,存入Firebase Firestore/实时数据库 FirebaseFirestore.getInstance() .collection("user_fcm_tokens") .document(currentUser.getUid()) .set(new HashMap<String, Object>() {{ put("token", fcmToken); put("update_time", new Date()); }}); }); } });
2. 处理用户退出登录的场景
用户退出时,要把对应令牌从存储中移除,避免后续误发通知:
// 退出登录方法中添加令牌清理逻辑 FirebaseAuth.getInstance().signOut(); FirebaseMessaging.getInstance().getToken() .addOnCompleteListener(tokenTask -> { if (tokenTask.isSuccessful()) { String currentToken = tokenTask.getResult(); // 从数据库删除该令牌的绑定记录 FirebaseFirestore.getInstance() .collection("user_fcm_tokens") .whereEqualTo("token", currentToken) .get() .addOnCompleteListener(queryTask -> { if (queryTask.isSuccessful()) { for (QueryDocumentSnapshot doc : queryTask.getResult()) { doc.getReference().delete(); } } }); // 可选:删除本地令牌,暂时禁用该设备的通知接收 FirebaseMessaging.getInstance().deleteToken(); } });
3. 发送通知时仅针对已登录用户的令牌
不要使用主题订阅(未登录用户可能也会订阅),而是从数据库取出所有已绑定用户的令牌,批量推送:
// 后端用Firebase Admin SDK发送通知的示例 FirebaseFirestore.getInstance().collection("user_fcm_tokens").get() .addOnCompleteListener(task -> { if (task.isSuccessful()) { List<String> targetTokens = new ArrayList<>(); for (QueryDocumentSnapshot doc : task.getResult()) { targetTokens.add(doc.getString("token")); } // 构建通知内容 Message message = Message.builder() .setNotification(Notification.builder() .setTitle("专属通知") .setBody("只有登录用户才能看到这条消息!") .build()) .setTokens(targetTokens) .build(); // 批量发送 FirebaseMessaging.getInstance().sendEachForMulticast(message); } });
额外注意事项
- 处理令牌更新:FCM令牌可能因设备重启、应用重装等情况变化,所以在
onNewToken方法中要判断用户是否已登录,已登录则更新数据库中的令牌:
@Override public void onNewToken(String newToken) { super.onNewToken(newToken); FirebaseUser currentUser = FirebaseAuth.getInstance().getCurrentUser(); if (currentUser != null) { // 用户已登录,更新数据库令牌 FirebaseFirestore.getInstance() .collection("user_fcm_tokens") .document(currentUser.getUid()) .update("token", newToken, "update_time", new Date()); } }
- 不要在应用启动时自动上传令牌,确保只有登录后的用户才会被纳入通知列表。
内容的提问来源于stack exchange,提问作者digital_pro
相关产品推荐
相关产品推荐

