Chrome插件与Android设备间FCM推送及消息交互实现问题
一、从Chrome插件向Android设备发送FCM审批通知
前端Chrome插件不能直接调用Firebase Admin SDK(会泄露服务端密钥),必须通过Firebase Cloud Functions作为中间层来发送FCM通知,具体步骤如下:
关联用户UID与Android设备令牌
Android端登录Firebase Auth后,获取FCM设备令牌,将令牌与当前用户的UID绑定,存储到Firestore的users/{uid}/deviceTokens集合里(Realtime Database也可以)。这样插件登录后就能通过用户UID找到对应的设备令牌。编写Cloud Function发送FCM通知
创建一个Callable类型的云函数,用来处理插件的通知请求,用Admin SDK发送FCM消息:// Cloud Functions index.js const functions = require("firebase-functions"); const admin = require("firebase-admin"); admin.initializeApp(); exports.sendApprovalRequest = functions.https.onCall(async (data, context) => { // 校验调用者身份,确保是已登录用户 if (!context.auth) { throw new functions.https.HttpsError("unauthenticated", "用户未登录"); } const userId = context.auth.uid; // 从Firestore拉取该用户绑定的所有设备令牌 const tokenSnapshot = await admin.firestore() .collection(`users/${userId}/deviceTokens`) .get(); const tokens = tokenSnapshot.docs.map(doc => doc.id); if (tokens.length === 0) { throw new functions.https.HttpsError("not-found", "未找到关联的设备令牌"); } // 构造FCM通知内容 const message = { notification: { title: "登录审批请求", body: "Chrome插件请求登录,请确认是否批准" }, data: { type: "approval", userId: userId }, tokens: tokens }; // 批量发送通知 const response = await admin.messaging().sendMulticast(message); return { successCount: response.successCount, failureCount: response.failureCount }; });部署这个函数:先执行
npm install firebase-functions firebase-admin,再用firebase deploy --only functions。Chrome插件调用云函数触发通知
插件登录Firebase Auth后,调用上述Callable函数触发通知发送:// Chrome插件弹出页/背景页的JS代码 import { getFunctions, httpsCallable } from "firebase/functions"; import { getAuth, onAuthStateChanged } from "firebase/auth"; // 初始化Firebase(提前在插件里配置好Firebase参数) const auth = getAuth(); const functions = getFunctions(); async function triggerApprovalNotification() { try { const sendRequest = httpsCallable(functions, "sendApprovalRequest"); const result = await sendRequest(); console.log(`通知发送结果:成功${result.data.successCount}条,失败${result.data.failureCount}条`); } catch (error) { console.error("发送通知失败:", error.message); } } // 用户登录成功后自动触发通知 onAuthStateChanged(auth, (user) => { if (user) { triggerApprovalNotification(); } });
二、Android批准后向插件回传密码列表
用Firestore实时监听实现数据同步,Android端上传密码后,插件能立刻收到并展示:
Android端处理通知点击并上传密码
当用户点击通知的「批准」按钮时,将密码列表和审批状态写入Firestore的users/{uid}/approvalStatus文档:Android端核心逻辑:获取当前登录用户的UID,创建/更新
approvalStatus文档,写入approved: true和passwordList: [/* 你的密码数组 */]Chrome插件实时监听审批结果
插件端监听approvalStatus文档的变化,一旦检测到批准状态,就读取密码列表并展示:// Chrome插件弹出页JS代码 import { getFirestore, doc, onSnapshot, updateDoc } from "firebase/firestore"; import { getAuth, onAuthStateChanged } from "firebase/auth"; const auth = getAuth(); const db = getFirestore(); function listenForApprovalResult() { onAuthStateChanged(auth, (user) => { if (!user) return; const approvalDocRef = doc(db, "users", user.uid, "approvalStatus"); // 实时监听文档变化 const unsubscribe = onSnapshot(approvalDocRef, (snapshot) => { const data = snapshot.data(); if (data && data.approved) { // 展示密码列表 renderPasswordList(data.passwordList); // 取消监听,避免重复触发 unsubscribe(); // 可选:重置审批状态,防止下次登录重复读取 updateDoc(approvalDocRef, { approved: false }); } }); }); } // 渲染密码列表到页面 function renderPasswordList(passwords) { const container = document.getElementById("password-list"); container.innerHTML = ""; passwords.forEach((pwd, index) => { const item = document.createElement("div"); item.className = "password-item"; item.textContent = `密码${index+1}:${pwd}`; container.appendChild(item); }); } // 页面加载时启动监听 document.addEventListener("DOMContentLoaded", listenForApprovalResult);
关键注意事项
- Chrome插件的
manifest.json必须配置Firebase OAuth客户端ID,并且启用对应的身份验证方法(比如邮箱密码、Google登录)。 - Android端要监听FCM令牌更新事件,及时同步到Firestore,避免令牌过期导致通知发送失败。
- Cloud Functions的权限要配置正确,确保只有已认证的用户能调用
sendApprovalRequest函数。
内容的提问来源于stack exchange,提问作者idk

