You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.14 12:36:03