Список FCM для нескольких устройств (токенов) - PullRequest
6 голосов
/ 14 января 2020

Моя цель - отправлять сообщения FCM на несколько токенов, содержащихся в карте документа, используя флаттер. Текущий код использует функцию «отправить все» и отправляет сообщения всем ожидаемым. Я надеюсь, что при вставке widget.document. [Token] или аналогичной ссылки будут отправлены только все элементы, содержащиеся в документе / списке. Firebase использует sendAll для отправки на указанные c устройства, поэтому я надеялся, что это сработает.

  • Использование ссылки на документ (токен) не возвращает ошибок, но также и сообщений

  • Использование снимка, содержащего только токены, возвращает ошибку, при которой могут быть переданы только данные c, наряду с некоторыми проблемами синтаксиса

  • использование api / http возвращает ошибку posturl возвращает null

В дополнение к вышеописанному, я также исследовал то, что пытались другие.

Вот некоторые из моих ошибок:

  • Пробный вызов:

  • [ ОШИБКА: flutter / lib / ui / ui_dart_state. cc (157)] Необработанное исключение: NoSuchMethodError: Метод '[]' вызван для нуля. * 104 3 *

  • Пробный вызов: post ("https://fcm.googleapis.com/fcm/send", тело: "{\" token \ ": ноль,

Это изображение моей структуры базы данных:

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}'),
      ));
    }
  }
}

Конечно заранее всем спасибо за ваше время.

1 Ответ

0 голосов
/ 24 января 2020
  1. Ваш экземпляр 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();

Выше был бы один документ. Затем вы можете отобразить документ и получить один токен, который вы можете передать в поле токена компонента Message.

Вы не передали токен в настоящую функцию Asyn c Messaging.sendToAll

final response = await Messaging.sendToAll (title: titleController.text, body: bodyController.text, );

Вышеприведенное должно содержать строку токена внутри тела, как показано ниже.

final response = await Messaging.sendToAll(
      title: titleController.text,
      body: bodyController.text,
      token:fcmTokenReturnedFromFirestore
    );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...