使用Firebase的Java安卓应用如何通过FCM发送带用户数据的定向通知
实现方案
整个实现流程可拆分为3个核心环节,具体操作如下:
1. 设备端绑定用户与FCM令牌
首先要建立用户唯一标识和FCM推送令牌的绑定关系,才能实现定向推送:
- 在Android端APP启动/用户登录时,获取当前设备的FCM注册令牌,将用户UID和令牌同步写入Firebase数据库(Firestore或 Realtime Database均可),Java代码示例:
FirebaseMessaging.getInstance().getToken() .addOnCompleteListener(task -> { if (!task.isSuccessful()) { Log.w("FCM_TOKEN", "获取令牌失败", task.getException()); return; } String fcmToken = task.getResult(); String currentUid = FirebaseAuth.getInstance().getCurrentUser().getUid(); // 写入用户令牌映射表 FirebaseFirestore.getInstance().collection("userFcmTokens") .document(currentUid) .set(new HashMap<String, Object>(){{ put("token", fcmToken); put("updateTime", System.currentTimeMillis()); }}); });
- 重写
FirebaseMessagingService的onNewToken方法,监听令牌更新事件,令牌过期更换时同步更新数据库的绑定关系。
2. 通知触发逻辑实现
推荐使用云函数触发方案,避免本地逻辑被篡改导致的虚假推送问题:
- 编写Firebase Cloud Functions,监听用户分数字段的更新事件,触发条件满足时自动拉取用户数据、组装通知内容、调用FCM接口推送:
以下为云函数核心逻辑示例,也可使用Java编写云函数
exports.sendScoreCongratulation = functions.firestore.document('users/{userId}') .onUpdate(async (change, context) => { const newUserData = change.after.data(); const oldUserData = change.before.data(); // 仅当分数首次达到10分时触发推送 if (newUserData.score >=10 && oldUserData.score <10) { const userId = context.params.userId; // 拉取对应用户的FCM令牌 const tokenDoc = await admin.firestore().collection("userFcmTokens").doc(userId).get(); const userFcmToken = tokenDoc.data().token; // 组装带用户个人数据的通知 const pushPayload = { token: userFcmToken, notification: { title: "积分达标通知", body: `恭喜${newUserData.nickname},你的积分已达到${newUserData.score}分,解锁专属徽章!` } }; // 调用FCM发送通知 await admin.messaging().send(pushPayload); } return null; });
- 如果是不需要服务端校验的轻量化场景,也可以直接在Android端监听用户分数变化,满足条件时本地组装内容弹出通知即可。
3. 自定义通知渲染(可选)
如果需要实现更复杂的通知样式,可选择FCM数据消息类型,而非直接发送通知消息,在设备端接收数据后本地渲染通知:
public class CustomFcmMessagingService extends FirebaseMessagingService { @Override public void onMessageReceived(@NonNull RemoteMessage remoteMessage) { super.onMessageReceived(remoteMessage); // 提取云函数传递的自定义数据 Map<String, String> pushData = remoteMessage.getData(); String nickname = pushData.get("nickname"); String score = pushData.get("score"); // 自定义组装通知后弹出 NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "score_notify_channel") .setSmallIcon(R.mipmap.ic_launcher) .setContentTitle("恭喜你达标啦") .setContentText(String.format("用户%s当前积分为%s分,解锁新权益", nickname, score)) .setPriority(NotificationCompat.PRIORITY_HIGH); NotificationManagerCompat.from(this).notify((int)System.currentTimeMillis(), builder.build()); } }
内容的提问来源于stack exchange,提问作者chang thenoob
相关产品推荐
相关产品推荐

