如何实现 Flutter Web 推送通知

Posted

技术标签:

【中文标题】如何实现 Flutter Web 推送通知【英文标题】:how to implement flutter web push notification 【发布时间】:2020-07-10 18:35:12 【问题描述】:

我想知道我是否可以在 Flutter Web 中实现推送通知? 我看到我可以使用firbase_messaging 为移动应用创建推送通知,但是可以将它用于网络应用吗?或任何其他替代方法来完成它?

【问题讨论】:

目前,Flutter 团队尚未在 Web 平台上提供 firebase_messaging 插件。该插件仅适用于 androidios。此外,您可以在 Flutter 应用程序之外仅使用 html&js 使用 firebase 消息传递,但我认为您不想要这种方式。希望他们也支持网络 firebase_messaging @Mohith7548 我只是希望它发生我不在乎如何?你能告诉我如何用js和html做到这一点吗?因为我从来没有用这些开发过网络 这是一个很好的文档firebase.google.com/docs/cloud-messaging/js/client 我试过了,但遇到了错误An error occurred while retrieving token: FirebaseError: Messaging: A problem occured while subscribing the user to FCM: Request contains an invalid argument. (messaging/token-subscribe-failed). (messaging/token-subscribe-failed) 【参考方案1】:

我在考虑你已经建立了一个flutter-web项目并且有一个firebase项目。

在flutter项目文件夹中,打开index.html并将这些脚本放在head部分。

<script src="https://www.gstatic.com/firebasejs/7.14.4/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.14.4/firebase-analytics.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.14.4/firebase-messaging.js"></script>

然后,在正文中,在加载 main.dart.js 脚本之前附加代码。

  <script src="./firebase-messaging-sw.js"></script>
  <script src="myjs.js"></script>
  <script src="main.dart.js" type="application/javascript"></script>

(其中 myjs.js 是您要编写代码的任何文件,但 firebase-messaging-sw.js 必须在其中。)

现在,在 index.html 目录中创建两个文件:

    firebase-messaging-sw.js myjs.js(无论您选择什么名称)

在firebase-messaging-sw.js中,只写

console.log("")

在 myjs.js 中(同样,无论您选择什么文件名),编写以下代码:

var firebaseConfig = 
    apiKey: "YOUR_API_KEY",
    authDomain: "~~~~~~",
    databaseURL: "~~~~~",
    projectId: "~~~~~~",
    storageBucket: "~~~~~~",
    messagingSenderId: "~~~~~~",
    appId: "~~~~~~~~~~~~~",
    measurementId: "~~~~~~~~~~~"
;

firebase.initializeApp(firebaseConfig);
firebase.analytics();

var messaging = firebase.messaging()

messaging.usePublicVapidKey('Your Key');

messaging.getToken().then((currentToken) => 
    console.log(currentToken)
)

您可以从 Firebase 控制台的项目设置中找到这些凭据。您将在您添加的网络应用程序中找到 firebaseConfig 详细信息。 对于密钥,您必须生成一个新对。转到项目设置中的 Cloud Messaging,您可以在那里生成一个新对。

当您运行应用程序时(flutter run -d chrome),您可以在控制台日志中找到您的令牌。复制该令牌。

从侧面抽屉的云消息部分,我们可以编写一个新通知。 在标题和文本中输入您喜欢的任何内容。 点击发送测试消息。 粘贴您从控制台复制的令牌,然后单击测试。

你可以看到弹出的通知。

您可以参考this article 和firebase documentation 了解更多信息。

【讨论】:

收到通知就可以了。如何获取通知标题和内容以及如何在 UI 中使用? 我按照上面的说明进行操作。我的网站现在请求发送通知的权限,但是当我通过云消息传递 Web 控制台发送通知时,什么也没有发生。我在本地和外部托管环境中对此进行了测试。我需要编辑 pubspec.yaml 中的任何内容吗?还有其他推荐吗? 要考虑的另一件事是消息传递不适用于 Safari 浏览器。您的 Web 应用程序将显示一个空白页面。这是因为 Safari 不支持 FCM firebase.google.com/support/guides/environments_js-sdk【参考方案2】:
To implement push notifications and open the app on notification click you need to Change in three files.


1) Firebase-Messaging-sw.js


importScripts("https://www.gstatic.com/firebasejs/7.23.0/firebase-app.js");
importScripts("https://www.gstatic.com/firebasejs/7.23.0/firebase-messaging.js");
firebase.initializeApp(
         apiKey: "",
           authDomain: "",
           projectId: "",
           storageBucket: "",
           messagingSenderId: "",
           appId: "",
           measurementId: ""
);
const messaging = firebase.messaging();


messaging.setBackgroundMessageHandler(function (payload) 
    const promiseChain = clients
        .matchAll(
            type: "window",
            includeUncontrolled: true
        )
        .then(windowClients => 
            for (let i = 0; i < windowClients.length; i++) 
                const windowClient = windowClients[i];
                windowClient.postMessage(payload);
            
        )
        .then(() => 
            const title = payload.notification.title;
            const options = 
                body: payload.notification.score
              ;
            return registration.showNotification(title, options);
        );
    return promiseChain;
);
self.addEventListener('notificationclick', function (event) 
    console.log('notification received: ', event)
);


index.html

<!DOCTYPE html>
<html>
<head>
    <!--
      If you are serving your web app in a path other than the root, change the
      href value below to reflect the base path you are serving from.

      The path provided below has to start and end with a slash "/" in order for
      it to work correctly.

      Fore more details:
      * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
    -->
    <base href="/">

    <meta charset="UTF-8">
    <meta content="IE=Edge" http-equiv="X-UA-Compatible">
    <meta name="description" content="Share pictures and information with other collectors of historical artifacts">

    <!-- iOS meta tags & icons -->
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <meta name="apple-mobile-web-app-title" content="Militrade">
    <link rel="apple-touch-icon" href="icons/Icon-192.png">

    <!-- Favicon -->
    <link rel="shortcut icon" type="image/x-icon" href="favicon.ico"/>
    <link rel="icon" type="image/x-icon" href="favicon.ico"/>

    <title>Militrade</title>
    <link rel="manifest" href="manifest.json">
</head>
<body>
<script>
  if ('serviceWorker' in navigator) 
    window.addEventListener('load', function () 
     navigator.serviceWorker.register("/firebase-messaging-sw.js");
   );
  
 </script>
<!-- This script installs service_worker.js to provide PWA functionality to
     application. For more information, see:
     https://developers.google.com/web/fundamentals/primers/service-workers -->
<!-- The core Firebase JS SDK is always required and must be listed first -->

<script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-app.js"></script>

<!-- TODO: Add SDKs for Firebase products that you want to use
   https://firebase.google.com/docs/web/setup#available-libraries -->

<script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-analytics.js"></script>

<script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-firestore.js"></script>

<script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-auth.js"></script>

<script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-messaging.js"></script>

<script src="https://www.gstatic.com/firebasejs/7.20.0/firebase-storage.js"></script>

<script>
  // Your web app's Firebase configuration
  // For Firebase JS SDK v7.20.0 and later, measurementId is optional
  var firebaseConfig = 
     apiKey: "",
    authDomain: "",
    projectId: "",
    storageBucket: "",
    messagingSenderId: "",
    appId: "",
    measurementId: ""
  ;
  // Initialize Firebase
  firebase.initializeApp(firebaseConfig);
  firebase.analytics();
</script>
<script src="main.dart.js" type="application/javascript"></script>
<script type="text/javascript">
    let useHtml = true;
    if(useHtml) 
      window.flutterWebRenderer = "html";
     else 
      window.flutterWebRenderer = "canvaskit";
    
  </script>



<script>
    if ("serviceWorker" in navigator) 
      window.addEventListener("load", function () 
        navigator.serviceWorker.register("/flutter_service_worker.js");
        navigator.serviceWorker.register("/firebase-messaging-sw.js");
      );
    
  </script>


</body>
</html>

then create push_notification_services.dart file for send push notification


import 'dart:async';
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:http/http.dart' as http;

final String serverToken =
    '';

Future<Map<String, dynamic>> sendPushNotification(
    @required String message,
    @required String fcmToken,
    @required String title) async 
  print(fcmToken);

  await http.post(
    Uri.parse('https://fcm.googleapis.com/fcm/send'),
    headers: <String, String>
      'Content-Type': 'application/json',
      'Authorization': 'key=$serverToken',
    ,
    body: jsonEncode(
      <String, dynamic>
        'notification': <String, dynamic>
           "click_action" : ".EditPostPage",
          'body': message,
          'title': '$title',
          'sound': 'default'
        ,
        'priority': 'high',
        'data': <String, dynamic>
          'click_action': 'FLUTTER_NOTIFICATION_CLICK',
          'id': '1',
          'status': 'done'
        ,
        'to': fcmToken.toString().trim(),
      ,
    ),
  );
  final Completer<Map<String, dynamic>> completer =
      Completer<Map<String, dynamic>>();

 
  return completer.future;



After 3 days I can do it and it's properly working well for me. hope it's helpful for you.
 

【讨论】:

以上是关于如何实现 Flutter Web 推送通知的主要内容,如果未能解决你的问题,请参考以下文章

当应用程序关闭时在 Flutter 中推送通知

如何在颤振中实现推送通知

如何获取 FCM-Django 推送通知的 registration_id (flutter app)

如何将 Bitmap 转换为 AndroidBitmap 以在 Flutter 中推送通知?

如何从 Asp.net 核心向 Flutter 应用发送推送通知

如何在接收基于 Flutter 构建的 FCM 推送通知时修复应用程序崩溃