Flutter:如何使用FCM以编程方式发送推送通知

时间:2019-01-26 15:58:15

标签: android flutter google-cloud-firestore

我正在创建一个聊天应用程序,并且如果该人有新消息,我想使用fcm发送通知,但是我不知道该如何进行。我发现的所有教程都用于从Firebase发送消息。但是我想在有新消息发送给该人时自动发送

3 个答案:

答案 0 :(得分:3)

我将在此处列出一些我已回答并回答的相关问题。我想您会在聊天应用程序中找到许多有关使用Firebase云消息传递(FCM)的相关信息。

  1. Is FCM the only way to build a chat app ?
  2. Suggested approach to use FCM in a chat app
  3. Is using topics a better solution then using the fcmToken in a chat app?
  4. Problems with FCM onMessage while app is in background
  5. Problem: after logoff, user continues to receive notifications

祝你好运!

答案 1 :(得分:2)

如果使用Firebase,可能的解决方法应为:

您需要为特定用户存储每个firebase FCM令牌(此处需要考虑到用户可以同时从多个设备登录其帐户),以便存储 userId 和他的 deviceUniqueId 扑朔迷离,您可以从device_info https://pub.dev/packages/device_info中获得它:

  String identifier;
  final DeviceInfoPlugin deviceInfoPlugin = new DeviceInfoPlugin();
  try {
    if (Platform.isAndroid) {
      var build = await deviceInfoPlugin.androidInfo;
      identifier = build.id.toString();
    } else if (Platform.isIOS) {
      var data = await deviceInfoPlugin.iosInfo;
      identifier = data.identifierForVendor;//UUID for iOS
    }
  } on PlatformException {
    print('Failed to get platform version');
  }

之后,要获取Firebase为每个设备提供的唯一CFM令牌,您可以使用Firebase firebase_messaging插件(https://pub.dev/packages/firebase_messaging getToken()来获取它,并将该令牌插入firestore (或您要存储的其他数据库)

  FirebaseMessaging firebaseMessaging = new FirebaseMessaging();

  firebaseMessaging.requestNotificationPermissions(
      const IosNotificationSettings(sound: true, badge: true, alert: true));
  firebaseMessaging.onIosSettingsRegistered
      .listen((IosNotificationSettings settings) {
    print("Settings registered: $settings");
  });

  firebaseMessaging.getToken().then((token){

    print('--- Firebase toke here ---');
    Firestore.instance.collection(constant.userID).document(identifier).setData({ 'token': token});
    print(token);

  });

此后,您可以为一个用户插入一个或多个连接到多个设备的FCM令牌。 1个用户... n个设备,1个设备... 1个唯一令牌,可从Firebase获取推送通知。

在向该人发送新消息时自动发送:现在您需要调用Firestore API(确实非常快,但是需要注意此处使用的计划限制)或另一个API调用(如果您将令牌存储到另一个数据库中),以便获取每个用户的令牌并发送推送通知。

要从Flutter发送推送通知,可以使用Future异步功能。 Ps:我在此​​处传递一个列表作为参数,以便使用“ registration_ids” 代替“ to” ,如果用户已经登录到多个设备上。

Future<bool> callOnFcmApiSendPushNotifications(List <String> userToken) async {

  final postUrl = 'https://fcm.googleapis.com/fcm/send';
  final data = {
    "registration_ids" : userToken,
    "collapse_key" : "type_a",
    "notification" : {
      "title": 'NewTextTitle'
      "body" : 'NewTextBody',
    }
  };

  final headers = {
    'content-type': 'application/json',
    'Authorization': constant.firebaseTokenAPIFCM
  };

  final response = await http.post(postUrl,
      body: json.encode(data),
      encoding: Encoding.getByName('utf-8'),
      headers: headers);

  if (response.statusCode == 200) {
    // on success do sth
    print('test ok push CFM');
    return true;
  } else {
    print(' CFM error');
    // on failure do sth
    return false;
  }
}

您还可以检查来自邮递员的邮寄电话以进行一些测试。 POST请求 在标题上添加:

  1. key 具有 value key = AAAAO ........的授权//项目概述->云消息传递->服务器密钥
  2. 具有 value application / json的
  3. key 内容类型

然后在身体上添加

{
 "registration_ids" :[ "userUniqueToken1", "userUniqueToken2",... ],
 "collapse_key" : "type_a",
 "notification" : {
     "body" : "Test post",
     "title": "Push notifications E"
 }
}

“ registration_ids” 将其发送到多个令牌(同一用户同时登录多个设备) “至” ,以便将其发送到单个令牌(每个用户一个设备/或始终更新与其设备连接并具有1个令牌... 1个用户的用户令牌)

答案 2 :(得分:2)

    //Notification Sending Side Using Dio flutter Library to make http post request

        static Future<void> sendNotification(receiver,msg)async{

        var token = await getToken(receiver);
        print('token : $token');

        final data = {
          "notification": {"body": "Accept Ride Request", "title": "This is Ride Request"},
          "priority": "high",
          "data": {
            "click_action": "FLUTTER_NOTIFICATION_CLICK",
            "id": "1",
            "status": "done"
          },
          "to": "$token"
        };

        final headers = {
          'content-type': 'application/json',
          'Authorization': 'key=AAAAY2mZqb4:APA91bH38d3b4mgc4YpVJ0eBgDez1jxEzCNTq1Re6sJQNZ2OJvyvlZJYx7ZASIrAj1DnSfVJL-29qsyPX6u8MyakmzlY-MRZeXOodkIdYoWgwvPVhNhJmfrTC6ZC2wG7lcmgXElA6E09'
        };


        BaseOptions options = new BaseOptions(
          connectTimeout: 5000,
          receiveTimeout: 3000,
          headers: headers,
        );


        try {
          final response = await Dio(options).post(postUrl,
              data: data);

          if (response.statusCode == 200) {
            Fluttertoast.showToast(msg: 'Request Sent To Driver');
          } else {
            print('notification sending failed');
            // on failure do sth
          }
        }
        catch(e){
          print('exception $e');
        }




      }

      static Future<String> getToken(userId)async{

        final Firestore _db = Firestore.instance;

        var token;
        await _db.collection('users')
            .document(userId)
            .collection('tokens').getDocuments().then((snapshot){
              snapshot.documents.forEach((doc){
                token = doc.documentID;
              });
        });

        return token;


      }


    //Now Receiving End 

        class _LoginPageState extends State<LoginPage>
        with SingleTickerProviderStateMixin {

      final Firestore _db = Firestore.instance;
      final FirebaseMessaging _fcm = FirebaseMessaging();

      StreamSubscription iosSubscription;



    //this code will go inside intiState function 

    if (Platform.isIOS) {
          iosSubscription = _fcm.onIosSettingsRegistered.listen((data) {
            // save the token  OR subscribe to a topic here
          });

          _fcm.requestNotificationPermissions(IosNotificationSettings());
        }
        _fcm.configure(
          onMessage: (Map<String, dynamic> message) async {
            print("onMessage: $message");
            showDialog(
              context: context,
              builder: (context) => AlertDialog(
                content: ListTile(
                  title: Text(message['notification']['title']),
                  subtitle: Text(message['notification']['body']),
                ),
                actions: <Widget>[
                  FlatButton(
                    child: Text('Ok'),
                    onPressed: () => Navigator.of(context).pop(),
                  ),
                ],
              ),
            );
          },
          onLaunch: (Map<String, dynamic> message) async {
            print("onLaunch: $message");
            // TODO optional
          },
          onResume: (Map<String, dynamic> message) async {
            print("onResume: $message");
            // TODO optional
          },
        );

//saving token while signing in or signing up
 _saveDeviceToken(uid) async {
    // FirebaseUser user = await _auth.currentUser();

    // Get the token for this device
    String fcmToken = await _fcm.getToken();

    // Save it to Firestore
    if (fcmToken != null) {
      var tokens = _db
          .collection('users')
          .document(uid)
          .collection('tokens')
          .document(fcmToken);

      await tokens.setData({
        'token': fcmToken,
        'createdAt': FieldValue.serverTimestamp(), // optional
        'platform': Platform.operatingSystem // optional
      });
    }
  }