Моя цель - отправлять сообщения 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](https://i.stack.imgur.com/aQBng.png)
Наконец, вот мой код:
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}'),
));
}
}
}
Конечно заранее всем спасибо за ваше время.