当用户A使用Firebase Cloud功能和Flutter跟随用户B时如何接收通知

问题描述

我是使用Firebase函数的新手,我已经设置了环境并部署了可以正常工作的其他函数,但是,我想知道如何实现一个允许用户在有人开始关注它们时收到通知函数(在添加新ID时会通知该关注者的收藏集。)

这是一个数据库,当用户(A)跟随用户(B)时,该数据库将获得一个ID,任何用户都有自己的ID,因此当用户跟随​​另一个用户时,该用户(A)的ID将保存到用户(B)id({ _buildUserProfile() { double height = responsive.height(context); double width = responsive.width(context); String comment = widget.reviews.comments; int reviews = _posts.length; int followersNew = _followerCount; int likeCount = widget.reviews.likeCount; int point = reviews * 10; int point2 = followersNew * 30; int point3 = likeCount * 20; int totalPoints = point + point2 + point3; return Column( children: <Widget>[ Stack( children: <Widget>[ Container( decoration: Boxdecoration( color: Colors.blueGrey[300],BoxShadow: shadowList,image: decorationImage( image: NetworkImage(widget.imageUrl),fit: BoxFit.cover,),height: height / 2,width: width,child: Column( mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[ SizedBox( height: height / 50,SizedBox( height: height / 50,],SizedBox( height: height / 130,_productimage(),MessageFollowUnfollowEditButton( followOrUnfollow: _followOrUnfollow,isFollowing: _isFollowing,user: widget.user,reviewId: widget.authorId,imageUrl: widget.userImage,reviews: widget.reviews,currentUserId: widget.currentUserId,isTrue: widget.isTrue == true ? true : false,Padding( padding: EdgeInsets.fromLTRB(width / 22,5.0,width / 22,0.0),child: Row( children: <Widget>[ Expanded( child: Column( children: <Widget>[ Container( decoration: Boxdecoration( borderRadius: BorderRadius.circular( responsive.width(context) / 42),gradient: LinearGradient( colors: [ Colors.white,Colors.white,//aqui child: Padding( padding: EdgeInsets.all(width / 22),child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround,children: <Widget>[ Column( children: <Widget>[ Text( _posts.length.toString(),style: TextStyle( fontSize: width / 22,fontWeight: FontWeight.w600,Text( 'Opiniones',style: kjosefin,Column( children: <Widget>[ Text( _followerCount.toString(),Text( 'Seguidores',Column( children: <Widget>[ Row( children: <Widget>[ Icon( Icons.control_point,size: width / 20,color: Colors.orangeAccent,Text( totalPoints.toString(),style: TextStyle( fontSize: width / 22,Text( 'Puntaje',style: kjosefin.copyWith(fontSize: height / 70),Column( children: <Widget>[ Row( children: <Widget>[ Icon( Icons.favorite,color: Colors.redAccent,Text( '${widget.reviews.likeCount.toString()}',Text( 'Likes',SizedBox( height: height / 130,Container( width: width / 1.1,height: height / 8,decoration: Boxdecoration( BoxShadow: shadowList,color: Colors.white,borderRadius: BorderRadius.all( Radius.circular(height / 70),child: Center( child: Padding( padding: EdgeInsets.all(height / 70),child: Text( '"$comment"',overflow: TextOverflow.ellipsis,textAlign: TextAlign.center,maxLines: 9,style: kjosefin.copyWith(color: Colors.grey),) ],); } )。因此,我需要一个通知发送给用户(B)的函数,以获得新的关注者。

请参见下面的结构

enter image description here

使用“关注”或“取消关注”按钮创建用户个人资料的方法

class FollowerNotification extends StatefulWidget {
  static final String id = 'chat_list';
  final String currentUserId;
  final String peerId;
  final User user;
  FollowerNotification({Key key,this.currentUserId,this.peerId,this.user})
      : super(key: key);

  @override
  State createState() =>
      FollowerNotificationState(currentUserId: currentUserId);
}

class FollowerNotificationState extends State<FollowerNotification> {
  FollowerNotificationState({Key key,@required this.currentUserId});

  final String currentUserId;
  final FirebaseMessaging firebaseMessaging = FirebaseMessaging();
  final FlutterlocalnotificationsPlugin FlutterlocalnotificationsPlugin =
      FlutterlocalnotificationsPlugin();
  final GoogleSignIn googleSignIn = GoogleSignIn();
  bool isLoading = false;

  @override
  void initState() {
    super.initState();
    registerNotification();
    configlocalnotification();
  }

  void registerNotification() {
    firebaseMessaging.requestNotificationPermissions();
    firebaseMessaging.configure(
      onMessage: (Map<String,dynamic> message) {
        print('onMessage: $message');
        Platform.isAndroid
            ? showNotification(message['notification'])
            : showNotification(message['aps']['alert']);
        return;
      },onResume: (Map<String,dynamic> message) {
        print('onResume: $message');
        return;
      },onLaunch: (Map<String,dynamic> message) {
        print('onLaunch: $message');
        return;
      },);

    firebaseMessaging.getToken().then(
      (token) {
        print('token: $token');
        Firestore.instance
            .collection('users')
            .document(widget.currentUserId)
            .updateData({'pushToken': token});
      },).catchError(
      (err) {
        Fluttertoast.showToast(msg: err.message.toString());
      },);
  }

  void configlocalnotification() {
    var initializationSettingsAndroid =
        new AndroidInitializationSettings('app_icon');
    var initializationSettingsIOS = new IOSInitializationSettings();
    var initializationSettings = new InitializationSettings(
        initializationSettingsAndroid,initializationSettingsIOS);
    FlutterlocalnotificationsPlugin.initialize(initializationSettings);
  }

  void showNotification(message) async {
    var androidplatformChannelSpecifics = new AndroidNotificationDetails(
      Platform.isAndroid
          ? 'com.dfa.Flutterchatdemo'
          : 'com.duytq.Flutterchatdemo','Flutter chat demo','your channel description',playSound: true,enableVibration: true,importance: Importance.Max,priority: Priority.High,);
    var iOSPlatformChannelSpecifics = new IOSNotificationDetails();
    var platformChannelSpecifics = new NotificationDetails(
        androidplatformChannelSpecifics,iOSPlatformChannelSpecifics);

    print(message);
    print(message['body'].toString());
    print(json.encode(message));

    await FlutterlocalnotificationsPlugin.show(0,message['title'].toString(),message['body'].toString(),platformChannelSpecifics,payload: json.encode(message));

    await FlutterlocalnotificationsPlugin.show(
        0,'plain title','plain body',payload: 'item x');
  }

通知

const functions = require('firebase-functions');

const admin = require('firebase-admin')
admin.initializeApp()


exports.sendNotification = functions.firestore
 .document('messages/{groupId1}/{groupId2}/{message}')
 .onCreate((snap,context) => {
   console.log('----------------start function--------------------')

   const doc = snap.data()
   console.log(doc)

   const idFrom = doc.idFrom
   const idTo = doc.idTo
   const contentMessage = doc.content

   // Get push token user to (receive)
   admin
     .firestore()
     .collection('users')
     .where('id','==',idTo)
     .get()
     .then(querySnapshot => {
       querySnapshot.forEach(userTo => {
         console.log(`Found user to: ${userTo.data().nickname}`)
         if (userTo.data().pushToken && userTo.data().chattingWith !== idFrom) {
           // Get info user from (sent)
           admin
             .firestore()
             .collection('users')
             .where('id',idFrom)
             .get()
             .then(querySnapshot2 => {
               querySnapshot2.forEach(userFrom => {
                 console.log(`Found user from: ${userFrom.data().nickname}`)
                 const payload = {
                   notification: {
                     title: `You have a message from "${userFrom.data().nickname}"`,body: contentMessage,badge: '1',sound: 'default'
                   }
                 }
                 // Let push to the target device
                 admin
                   .messaging()
                   .sendToDevice(userTo.data().pushToken,payload)
                   .then(response => {
                     console.log('Successfully sent message:',response)
                   })
                   .catch(error => {
                     console.log('Error sending message:',error)
                   })
               })
             })
         } else {
           console.log('Can not find pushToken target user')
         }
       })
     })
   return null
 })

我在index.js中拥有的代码

{{1}}

解决方法

所有异步工作完成后,您需要终止Cloud Function,请参见doc。对于后台触发的Cloud Function(例如Cloud Firestore函数onCreate触发器),您必须返回异步方法调用返回的承诺链。

在您的情况下,不仅您不退回get()返回的承诺,而且末尾还有一个return null;,这可能表明Cloud Function平台可以清理您的功能在异步工作完成之前。

以下方法可以解决这个问题(未经测试)。请注意,我假设仅存在一个与where('id','==',idTo)相对应的文档,以及仅一个与where('id',idFrom)相对应的文档。

exports.sendNotification = functions.firestore
    .document('messages/{groupId1}/{groupId2}/{message}')
    .onCreate((snap,context) => {

        const doc = snap.data()
        console.log(doc)

        const idFrom = doc.idFrom
        const idTo = doc.idTo
        const contentMessage = doc.content

        // Get push token user to (receive)
        return admin
            .firestore()
            .collection('users')
            .where('id',idTo)
            .get()
            .then(querySnapshot => {
                const userTo = querySnapshot.docs[0];
                console.log(`Found user to: ${userTo.data().nickname}`)
                if (userTo.data().pushToken && userTo.data().chattingWith !== idFrom) {
                    // Get info user from (sent)
                    return admin
                        .firestore()
                        .collection('users')
                        .where('id',idFrom)
                        .get();
                } else {
                    console.log('Can not find pushToken target user')
                    throw new Error('Can not find pushToken target user');
                }
            })
            .then(querySnapshot => {
                const userFrom = querySnapshot.docs[0];
                console.log(`Found user from: ${userFrom.data().nickname}`)
                const payload = {
                    notification: {
                        title: `You have a message from "${userFrom.data().nickname}"`,body: contentMessage,badge: '1',sound: 'default'
                    }
                }
                // Let push to the target device
                return admin
                    .messaging()
                    .sendToDevice(userTo.data().pushToken,payload);
            })
            .then(response => {
                console.log('Successfully sent message:',response);
                return null;
            })
            .catch(error => {
                console.log('Error sending message:',error);
                return null;
            });

    });