如何使用OneSignal与Flutter实现用户之间的通知发送功能
用户间互发通知(OneSignal+Flutter+Firebase)配置方案
1. 补全Player ID存储逻辑
你现在的代码只初始化了OneSignal,但没有将每个用户对应的唯一Player ID(即你提到的Token类标识)存储到Firebase,用户间发通知需要用该ID定位接收方。
首先修改initPlatformState方法,监听OneSignal的Player ID变化,同时结合Firebase登录状态,将ID同步到对应用户的Firestore文档:
Future<void> initPlatformState() async { OneSignal.shared.setAppId(oneSignalAppId); // 申请通知权限 OneSignal.shared.promptUserForPushNotificationPermission(); // 初始化时同步当前用户的Player ID OneSignal.shared.getDeviceState().then((deviceState) { final playerId = deviceState?.userId; if (playerId != null && FirebaseAuth.instance.currentUser != null) { // 更新当前登录用户的player_id字段 FirebaseFirestore.instance .collection('users') .doc(FirebaseAuth.instance.currentUser!.uid) .update({'player_id': playerId}); } }); // 监听通知点击事件,可自定义跳转逻辑,比如跳转到对应聊天页 OneSignal.shared.setNotificationOpenedHandler((openedResult) { // 自定义跳转逻辑写在这里 }); }
同时修改用户注册登录的_submitAuthForm方法,注册/登录成功后直接写入最新的Player ID:
void _submitAuthForm( String email, String userName, String password, File image, bool isLogin, BuildContext ctx, ) async { UserCredential authResult; if (!isLogin) { authResult = await _auth.createUserWithEmailAndPassword( email: email, password: password); // 获取当前设备的Player ID final deviceState = await OneSignal.shared.getDeviceState(); final playerId = deviceState?.userId; await FirebaseFirestore.instance .collection('users') .doc(authResult.user.uid) .set({ 'username': userName, 'email': email, 'image_url': url, 'player_id': playerId, // 新增字段存储Player ID }); } else { // 登录场景也同步更新Player ID,避免设备更换、卸载重装导致ID变更 authResult = await _auth.signInWithEmailAndPassword(email: email, password: password); final deviceState = await OneSignal.shared.getDeviceState(); final playerId = deviceState?.userId; if (playerId != null) { await FirebaseFirestore.instance .collection('users') .doc(authResult.user.uid) .update({'player_id': playerId}); } } }
2. 开启OneSignal客户端发送权限
登录OneSignal控制台进入对应应用设置:
- 进入Messaging页面,开启
Allow notifications to be sent from your client side code选项 - 进入Keys & IDs页面,留存你的REST API密钥,若后续需要服务端转发通知会用到
3. 实现用户间发送通知逻辑
在聊天页面的发消息触发方法中,先查询接收方的Player ID,再调用OneSignal接口发送通知,示例代码如下:
Future<void> sendChatNotification(String receiverUid, String messageContent, String senderName) async { // 从Firestore拉取接收方的Player ID final receiverDoc = await FirebaseFirestore.instance.collection('users').doc(receiverUid).get(); final receiverPlayerId = receiverDoc.data()?['player_id']; // 接收方无有效ID时直接返回,可自行加兜底逻辑 if (receiverPlayerId == null) return; // 构造通知内容调用发送接口 var notification = OSCreateNotification( playerIds: [receiverPlayerId], heading: senderName, content: messageContent, additionalData: { "sender_uid": FirebaseAuth.instance.currentUser?.uid, "type": "chat_message" }, ); await OneSignal.shared.postNotification(notification); }
4. 可选优化
- 可在Firestore中为
player_id字段添加索引,提升查询速度 - 新增发送失败兜底逻辑,比如接收方没有有效Player ID时,将通知暂存到待发送队列,等对方登录后再触发推送
- 可添加前台通知展示逻辑,用户在应用内时也能看到新消息提醒
内容的提问来源于stack exchange,提问作者Pannam T
相关产品推荐
相关产品推荐

