我的目标是使用Flutter向包含在文档映射中的多个令牌发送FCM消息。当前代码使用“发送全部”功能,它会按预期发送到所有人。我希望插入一个widget.document.[token]或类似引用,只发送给包含在文档/列表中的所有项。
Firebase使用sendAll发送到特定设备,所以我希望这个方法行得通。使用document(token)引用不会返回错误,但也没有消息
使用仅包含令牌的快照会返回错误,指出只能传递静态项目以及一些语法问题
使用api/http会返回posturl为null的错误
除了尝试上述方法外,我还研究了其他人尝试过的方法。
以下是我的一些错误:
尝试调用:
[ERROR: flutter/lib/ui/ui_dart_state.cc(157)] 未处理的异常:NoSuchMethodError:null上的方法“[]”被调用。
尝试调用:post("https://fcm.googleapis.com/fcm/send", body: "{\"token\":null,
这是我的数据库结构图片:
最后,这是我的代码:
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}'),
));
}
}
}
当然,提前感谢大家的时间。