在 flutter 中向特定用户 firebase 发送通知

Moh*_*iem 9 android dart flutter

当一个用户按下按钮时,如何向另一个用户发送通知?有人可以给我看一个代码片段吗?

我意识到这个问题之前被问过,但是,由于有“几个答案”,所以它被关闭了。提供的类似链接没有解释在flutter中发送通知。

Moh*_*iem 18

我已经弄清楚如何使用应用程序内功能将通知发送到另一台设备。

首先,您需要导入必要的包:

firebase_messaging
flutter_local_notifications

注意:您还将使用该http

另请注意:要将通知发送到另一个设备,您必须知道该设备的设备令牌。我更喜欢获取令牌并将其保存在 Firestore 或实时数据库中。这是获取设备令牌的代码。

String? mtoken = " ";

void getToken() async {
    await FirebaseMessaging.instance.getToken().then((token) {
      setState(() {
        mtoken = token;
      });
    });
  }
Run Code Online (Sandbox Code Playgroud)

该令牌将保存在 mtoken 中,您现在可以使用它作为后续步骤的令牌。

发送通知的代码

在您的 Firebase 项目中启用 FIrebase Cloud Functions,这必须使用 Firbebase Blaze 计划。

在我的functions文件夹中,我添加了这段代码index.js

 /* eslint-disable */
const functions = require("firebase-functions");
const admin = require("firebase-admin");

admin.initializeApp();

exports.sendNotification = functions.https.onCall(async (data, context) => {
  await admin.messaging().sendMulticast({
  tokens: data.tokens,
  notification: {
    title: data.title,
    body: data.body,
    imageUrl: data.imageUrl,
  },
});

Run Code Online (Sandbox Code Playgroud)

确保部署您的 Firebase 云功能。如果你看到这个,你就会知道它是否有效。

在此输入图像描述

您可以使用以下代码在 Flutter 应用程序中调用此函数

Future<void> sendNotification(
  tokens,
  String title,
  String body,
  String imageUrl,
) async {
  FirebaseFunctions functions =
      FirebaseFunctions.instanceFor(region: 'us-central1');

  try {
    final HttpsCallable callable = functions.httpsCallable('sendNotification');
    final response = await callable.call({
      'tokens': tokens,
      'title': title,
      'body': body,
      'imageUrl': imageUrl,
    });

    print('Message sent: ${response.data}');
  } catch (e) {
    print('Error sending message: $e');
  }
}
Run Code Online (Sandbox Code Playgroud)

接收通知的代码

下一步是请求向您的应用程序发送推送通知的权限。

  void requestPermission() async {
    FirebaseMessaging messaging = FirebaseMessaging.instance;

    NotificationSettings settings = await messaging.requestPermission(
      alert: true,
      announcement: false,
      badge: true,
      carPlay: false,
      criticalAlert: false,
      provisional: false,
      sound: true,
    );

    if (settings.authorizationStatus == AuthorizationStatus.authorized) {
      print('User granted permission');
    } else if (settings.authorizationStatus ==
        AuthorizationStatus.provisional) {
      print('User granted provisional permission');
    } else {
      print('User declined or has not accepted permission');
    }
  }
Run Code Online (Sandbox Code Playgroud)

(如果您在控制台中收到“用户拒绝或未接受权限”,请尝试退出您的应用程序,在主屏幕中找到该图标,按住应用程序图标,点击“应用程序信息”,点击“通知”,然后开启“所有[应用程序名称]通知”。

您还需要两个函数来加载 Firebase Cloud Messaging 通知,以及一个函数来监听通知。

加载 Firebase 云消息通知的代码:

 void loadFCM() async {
    if (!kIsWeb) {
      channel = const AndroidNotificationChannel(
        'high_importance_channel', // id
        'High Importance Notifications', // title
        importance: Importance.high,
        enableVibration: true,
      );

      flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();

      /// Create an Android Notification Channel.
      ///
      /// We use this channel in the `AndroidManifest.xml` file to override the
      /// default FCM channel to enable heads up notifications.
      await flutterLocalNotificationsPlugin
          .resolvePlatformSpecificImplementation<
              AndroidFlutterLocalNotificationsPlugin>()
          ?.createNotificationChannel(channel);

      /// Update the iOS foreground notification presentation options to allow
      /// heads up notifications.
      await FirebaseMessaging.instance
          .setForegroundNotificationPresentationOptions(
        alert: true,
        badge: true,
        sound: true,
      );
    }
  } 
Run Code Online (Sandbox Code Playgroud)

此函数用于侦听 Firebase Cloud Messaging 通知。

void listenFCM() async {
    FirebaseMessaging.onMessage.listen((RemoteMessage message) {
      RemoteNotification? notification = message.notification;
      AndroidNotification? android = message.notification?.android;
      if (notification != null && android != null && !kIsWeb) {
        flutterLocalNotificationsPlugin.show(
          notification.hashCode,
          notification.title,
          notification.body,
          NotificationDetails(
            android: AndroidNotificationDetails(
              channel.id,
              channel.name,
              // TODO add a proper drawable resource to android, for now using
              //      one that already exists in example app.
              icon: 'launch_background',
            ),
          ),
        );
      }
    });
  }
Run Code Online (Sandbox Code Playgroud)

初始化页面时,您将需要运行 loadFCM、listenFCM 和 requestPermission。

  void initState() {
    super.initState();
    requestPermission();
    loadFCM();
    listenFCM();
  }
Run Code Online (Sandbox Code Playgroud)

过时的方法

此代码已弃用,并且由于在应用程序中使用 API 密钥而包含安全问题,可以对其进行反向工程以使用 API 密钥作为应用程序发送通知。仅将此用于测试,因为您不需要 Firebase Cloud Functions 来执行此操作。

下一步是找到您的Firebase Cloud MessagingAPI 密钥。只需转到您的 Firebase 项目 > 项目设置 > 云消息传递,然后复制 下的 API 密钥即可完成此操作Cloud Messaging API (Legacy)

当您拥有 Firebase Cloud Messaging API 密钥时,这是在给定通知标题、正文和要发送到的设备令牌的情况下显示通知的代码。

  void sendPushMessage(String body, String title, String token) async {
    try {
      await http.post(
        Uri.parse('https://fcm.googleapis.com/fcm/send'),
        headers: <String, String>{
          'Content-Type': 'application/json',
          'Authorization':
              'key=REPLACETHISWITHYOURAPIKEY',
        },
        body: jsonEncode(
          <String, dynamic>{
            'notification': <String, dynamic>{
              'body': body,
              'title': title,
            },
            'priority': 'high',
            'data': <String, dynamic>{
              'click_action': 'FLUTTER_NOTIFICATION_CLICK',
              'id': '1',
              'status': 'done'
            },
            "to": token,
          },
        ),
      );
      print('done');
    } catch (e) {
      print("error push notification");
    }
  }
Run Code Online (Sandbox Code Playgroud)

现在你可以像这样调用这个函数:

sendPushMessage('Notification Body', 'Notification Title', 'REPLACEWITHDEVICETOKEN');

我希望这有帮助。

  • 您好,感谢您的宝贵评论。让我问一个问题,这个解决方案有安全问题,不是吗?如果您从客户端发送 API 密钥,它可以被捕获,这就是为什么在服务器端使用触发器是更好的方法?但是,是的,这种方式更容易,但也许不是最好的方法。你有什么看法@Mohammad Abd-elmoniem (2认同)