firebase - FCM 到多个设备( token )列表

标签 firebase flutter firebase-cloud-messaging

我的目标是使用 flutter 将 FCM 消息发送到包含在文档映射中的多个 token 。当前代码使用“全部发送”功能,并按预期发送给所有人。我希望插入一个widget.document.[token] 或类似的引用将只发送到文档/列表中包含的所有项目。
Firebase uses sendAll to send to specific devices so I was hoping this would work.

  • 使用文档( token )引用不会返回错误,但也不会返回消息
  • 使用仅包含 token 的快照会返回一个错误,该错误仅
    可以传递静态项,还有一些语法问题
  • 使用 api/http 返回错误 posturl 返回 null

  • 除了尝试上述方法外,我还研究了其他人尝试过的方法。
  • functions/index.ts, this is designed for mulitple tokens for single user
  • push list programmatically yielded some syntax errors, and post url null

  • 以下是我的一些错误:
  • 尝试调用:
  • [错误:flutter/lib/ui/ui_dart_state.cc(157)] 未处理的异常:NoSuchMethodError:在 null 上调用了方法“[]”。
  • 尝试调用:post("https://fcm.googleapis.com/fcm/send ", body: "{\"token\":null,

  • 这是我的数据库结构的图片:

    Firebase Database Structure

    最后,这是我的代码:
    import 'package:chat/screens2/alert_widget.dart';
    import 'package:cloud_firestore/cloud_firestore.dart';
    import 'package:firebase_messaging/firebase_messaging.dart';
    import 'package:flutter/foundation.dart';
    import 'package:flutter/material.dart';
    import 'package:geo_firestore/geo_firestore.dart';
    import 'package:geolocator/geolocator.dart';
    import 'package:chat/api/messaging.dart';
    import 'package:chat/models/messages.dart';
    import 'package:flutter/widgets.dart';
    
    
    class SendAlert extends StatefulWidget {
      static const String id = 'send_alert';
      final Message message;
    
      final url;
      final body;
      final title;
      final image;
      final content;
    
      SendAlert({
        Key key,
        this.title,
        this.url,
        this.body,
        this.message,
        this.image,
        this.content,
        String alertIdd,
      }) : super(key: key);
    
      get documents => null;
    
      SendAlertState createState() => SendAlertState();
    }
    
    Firestore firestore = Firestore.instance;
    GeoFirestore geoFirestore = GeoFirestore(firestore.collection('users'));
    
    class SendAlertState extends State<SendAlert> {
      FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
      TextEditingController roomnameController = TextEditingController();
      final TextEditingController titleController = TextEditingController();
      final TextEditingController bodyController = TextEditingController();
      final List<Message> messages = [];
    
    
      TextEditingController citystateController = TextEditingController();
    
      final db = Firestore.instance;
      get title => null;
      get body => null;
      get uid => null;
      get alertidd => null;
      var currentLocation;
      var clients = [];
    
      List<Map<String, dynamic>> _documents;
    
      void onBbackPressed(BuildContext context) => Navigator.pop(context);
    
    
      @override
      void initState() {
        super.initState();
    
            populateClientu();
    
        Geolocator().getCurrentPosition().then((currloc) {
          setState(() {
            currentLocation = currloc;
          });
        });
    
        _firebaseMessaging.onTokenRefresh.listen(sendTokenToServer);
        _firebaseMessaging.getToken();
    
        _firebaseMessaging.subscribeToTopic('all');
    
        _firebaseMessaging.configure(
          onMessage: (Map<String, dynamic> message) async {
            print("onMessage: $message");
            final notification = message['notification'];
            setState(() {
              messages.add(Message(
                  title: notification['title'], body: notification['body']));
            });
    
          },
          onLaunch: (Map<String, dynamic> message) async {
            print("onLaunch: $message");
    
            final notification = message['data'];
            setState(() {
              messages.add(Message(
                title: '${notification['title']}',
                body: '${notification['body']}',
              ));
            });
    
          },
          onResume: (Map<String, dynamic> message) async {
            print("onResume: $message");
          },
        );
        _firebaseMessaging.requestNotificationPermissions(
            const IosNotificationSettings(sound: true, badge: true, alert: true));
      }
    
    
    
    
    
    
    
      populateClientu() async {
        Position position = await Geolocator()
            .getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
        var queryLocation = GeoPoint(position.latitude, position.longitude);
    
        List<DocumentSnapshot> snapshots =
            await geoFirestore.getAtLocation(queryLocation, 10.0);
    
        final documents = snapshots.map((doc) {
          return doc.data;
        }).toList();
    
        setState(() {
          _documents = documents;
        });
    
      }
    
    
    
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(
              backgroundColor: Color.fromARGB(255, 4, 22, 36),
              title: Text('SEND MSG'),
              leading: IconButton(
                onPressed: () => this.onBbackPressed(context),
                icon: Icon(Icons.arrow_back),
              ),
            ),
            backgroundColor: Color.fromARGB(255, 4, 22, 36),
            body: 
    
                  Container(
                      width: 250,
                      height: 35,
                      margin: EdgeInsets.only(top: 4),
                      child: Opacity(
                          opacity: 0.8,              
                  child: FlatButton(
    
                      color: Color.fromARGB(51, 255, 255, 255),
                      shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.all(Radius.circular(10)),
                        side: BorderSide(
                          width: 0.75,
                          color: Color.fromARGB(255, 255, 255, 255),
                          style: BorderStyle.solid,
                        ),
                      ),
                      textColor: Color.fromARGB(255, 255, 255, 255),
                      padding: EdgeInsets.all(0),
                      child: Text(
                        "SEND ALERT",
                        style: TextStyle(
                          fontSize: 12,
                          letterSpacing: 2,
                          fontFamily: "Roboto",
                          fontWeight: FontWeight.w500,
                        ),
                        textAlign: TextAlign.left,
                      ),
                      onPressed: () async {
    
    
    
      //                const querySnapshot = await db     <--- I suspect the document map has extra unused data.  I thought maybe FCM will only accept and array of tokens, this did not work either.
        //              .collection('users')
          //            .document()
            //          .collection('token')
              //        .get();
    
    
    
    
                        sendNotification();
    
                        Navigator.push(
                            context,
                            MaterialPageRoute(
                                builder: (context) => AlertWidget()));
                      })))
                                    );
      }
    
      void sendTokenToServer(String fcmToken) {
        print('Token: $fcmToken');
      }
    
      Future sendNotification() async {
      //Future sendNotification(documents(token)) async {   <--- I tried to pass widget.document[token]
        final response = await Messaging.sendToAll(
          title: titleController.text,
          body: bodyController.text,
        );
    
        if (response.statusCode != 200) {
          Scaffold.of(context).showSnackBar(SnackBar(
            content:
                Text('[${response.statusCode}] Error message: ${response.body}'),
          ));
        }
      }
    }
    

    当然,提前感谢大家的时间。

    最佳答案

  • 您的 firestore 实例返回用户文档列表。您需要遍历文档以仅提取文档中的标记并将它们放入字符串列表中,然后将其传递给 FCM。

  • 如果您比较您的屏幕截图和应该返回文档的代码。他们不对齐。你可以改变它。
    //                const querySnapshot = await db     <--- I suspect the document map has extra unused data.  I thought maybe FCM will only accept and array of tokens, this did not work either.
        //              .collection('users')
          //            .document()
            //          .collection('token')
              //        .get();
    


      //                const querySnapshot = await db     <--- I suspect the document map has extra unused data.  I thought maybe FCM will only accept and array of tokens, this did not work either.
        //              .collection('users')
          //            .document("DOCUMENT ID")
              //        .get();
    

    以上将得到一个文件。然后,您可以映射文档并获取单个 token ,您可以将其传递到 Message 组件的 token 字段中。
  • 您尚未将 token 传递到实际的异步函数 Messaging.sendToAll

    最终响应 = 等待 Messaging.sendToAll(
    标题:titleController.text,
    正文:bodyController.text,
    );

  • 上面应该在正文中包含一个 token 字符串,如下所示。
    final response = await Messaging.sendToAll(
          title: titleController.text,
          body: bodyController.text,
          token:fcmTokenReturnedFromFirestore
        );
    

    关于firebase - FCM 到多个设备( token )列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59733469/

    相关文章:

    android - E/FirebaseInstanceId : Error while delivering the message: ServiceIntent not found

    javascript - 使用 jQuery (Javascript) 的 Firebase 推送通知

    java - Flutter+Android Studio : Can't resolve Java symbols from external libraries

    android - 在 android 中使用改造库发送 fcm 推送通知

    ios - 为什么我的 UITableViewCells 不显示信息?

    typescript - 如何从 Firebase SDK 导入 Cloud Firestore Timestamp 对象?

    android - 在 sqflite 数据库创建时插入记录

    flutter - 如何通过 dart 中的另一个项目列表搜索对象列表

    reactjs - Firebase 云消息传递在窗口焦点之外时不显示通知

    swift - Firebase 中其他两个值之间的查询值