Функция облачных сообщений Firebase для веба Flutter не отвечает.

Вопрос или проблема

Я пытаюсь вызвать функцию requestPermission() из FirebaseMessaging. По какой-то причине это ничего не возвращает, и выполнение функции останавливается.

Я программирую на VSCode на машине с Windows 11, работая в вебе (Edge). Я также пытался на андроид-телефоне без успеха.

Вот код:

void initPushNotification() async {
    print("в асинхронном режиме");
    String? fcmToken;
    try {
      final fcm = FirebaseMessaging.instance;
      print("requestperm");
      final response = await fcm.requestPermission();
      print(response.authorizationStatus.name);
      print("получили разрешение");

      if (kIsWeb) {
        print("это веб");

        fcmToken = await fcm.getToken(
            vapidKey:
                "ЗДЕСЬ КЛЮЧ VAPID");
        print("получили токен");
      } else {
        fcmToken = await fcm.getToken();
      }
      print(
          fcmToken);
    } catch (err) {
      print(err);
    }
    print("конец асинхронного режима");
  }

  @override
  void initState() {
    super.initState();
    print("инициализация состояния");
    try {
      initPushNotification();
    } catch (err) {
      print("поймано");

      print(err);
    }
    print("завершение инициализации состояния");
  }

Вывод в консоли:

инициализация состояния
в асинхронном режиме
завершение инициализации состояния
requestperm

Некоторая информация в pubspec:

environment:
  sdk: ^3.5.3

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.8
  firebase_core: ^3.6.0
  firebase_auth: ^5.3.1
  firebase_storage: ^12.3.4
  image_picker: ^1.1.2
  cloud_firestore: ^5.4.4
  firebase_messaging: ^15.1.4

dev_dependencies:
  flutter_test:
    sdk: flutter

  flutter_lints: ^4.0.0

flutter:
  uses-material-design: true

У меня нет ошибок в консоли, даже в веб-консоли.

Я ожидал, что функция requestPermission() действительно запросит разрешения …

Я искал в интернете, чтобы найти некоторые решения и следовал документации firebase: https://firebase.flutter.dev/docs/messaging/overview и https://firebase.google.com/docs/cloud-messaging/flutter/receive?hl=fr.

Также пытаясь это сделать, даже если это выглядит немного подозрительно для меня:
Добавление данных в мой index.html в папке веб:

// Я знаю, что версия здесь неправильная, но я ожидал бы другой вид ошибки, если бы это было так
<script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-messaging.js"></script>
<script>
    const firebaseConfig = {
       apiKey: '...',
      appId: '...',
      messagingSenderId: '...',
      projectId: '...',
      authDomain: '...',
      storageBucket: '...',
    };
    firebase.initializeApp(firebaseConfig);
  </script>
  <script src="main.dart.js" type="application/javascript"></script>
  <script>
    if ("serviceWorker" in navigator) {
      window.addEventListener("load", function () {
        navigator.serviceWorker.register("/firebase-messaging-sw.js");
      });
    }
  </script>

firebase-messaging-sw.js:

importScripts('https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.10.0/firebase-messaging.js');

   /*Обновите с вашими конфигурациями*/
  const firebaseConfig = {
   apiKey: '...',
      appId: '...',
      messagingSenderId: '...',
      projectId: '...',
      authDomain: '...',
      storageBucket: '...',
 };
  firebase.initializeApp(firebaseConfig);
  const messaging = firebase.messaging();

  /*messaging.onMessage((payload) => {
  console.log('Сообщение получено. ', payload);*/
  messaging.onBackgroundMessage(function(payload) {
    console.log('Получено фоновое сообщение ', payload);

    const notificationTitle = payload.notification.title;
    const notificationOptions = {
      body: payload.notification.body,
    };

    self.registration.showNotification(notificationTitle,
      notificationOptions);
  });

Что я упускаю?

Следуйте этому пошаговому процессу

Шаг 1: Попробуйте запустить в Chrome, а не в браузере Edge
: -> Если работает, то не нужно изменять

Шаг 2: Если получите тот же результат в любом браузере

Например, если приложение не запускается или запускается, но ничего не отображается в браузере (например, пустой экран) и не возникает никаких ошибок.

Внесите следующие изменения в файл index.html в веб-каталоге вашего проекта

Проверьте, что следующая функция должна быть последней закладкой в файл index

  <script>
    window.addEventListener('load', function (ev) {
      // Загрузить main.dart.js
      _flutter.loader.loadEntrypoint({
        serviceWorker: {
          serviceWorkerVersion: serviceWorkerVersion,
        },
        onEntrypointLoaded: function (engineInitializer) {
          engineInitializer.initializeEngine().then(function (appRunner) {
            appRunner.runApp();
          });
        }
      });
    });
  </script>

  <script src="main.dart.js" type="application/javascript"></script>

Для большей справки я предоставляю вам весь файл index.html своего личного проекта flutter (TechCureIndia)


<!DOCTYPE html>
<html>

<head>

  <base href="/">

  <meta charset="UTF-8">
  <meta content="IE=Edge" http-equiv="X-UA-Compatible">
  <!-- Описание -->
  <meta name="description"
    content="Мы являемся экспертами в компьютерных рабочих станциях и игровых ПК | ПК для ИИ и глубокого обучения | ПК для архитектуры и инженерии | ПК для визуального дизайна и видеомонтажа | торговый ПК | ПК для аудиопродукции | игровые ПК | серии amd | пользовательская система охлаждения с жидкостью | оборудование для майнинга криптовалюты | Все ИТ-аксессуары и многое другое.">

  <!-- мета-теги и иконки для iOS -->
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black">
  <!-- Изменить TITLE -->
  <meta name="apple-mobile-web-app-title" content="Tech Cure India">
  <link rel="apple-touch-icon" href="icons/Icon-192.png">

  <!-- Значок -->
  <!-- <link rel="icon" type="image/png" href="favicon.png" /> -->

  <!-- Использовать .ico значок -->
  <link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
  <link rel="icon" href="favicon.ico" type="image/x-icon">

  <!-- Изменить TITLE -->
  <title>Tech Cure India</title>
  <link rel="manifest" href="manifest.json">

  <script>
    // Значение ниже внедрено сборкой flutter, не трогайте.
    const serviceWorkerVersion = "2091515534";
  </script>
  <!-- Этот скрипт добавляет код JS для инициализации flutter -->
  <script src="flutter.js" defer></script>

  <!-- Это для js в flutterWeb-->
  <script src="appscript.js" defer></script>
  <!-- Это для загрузки нашего css-файла-->
  <link rel="stylesheet" type="text/css" href="styles.css">

  <!-- CSS Toastify -->
  <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/toastify-js/src/toastify.min.css">

  <!-- Просмотр PDF -->
  <script>
    var dartPdfJsVersion = "3.2.146";
  </script>
</head>

<body>
  <!-- Индикатор загрузки ниже-->
  <div class="loading">
    <div class="loader"></div>
  </div>
  <!-- Индикатор загрузки выше-->

  <!-- <script src="main.dart.js" type="application/javascript"></script> -->
  <!-- Переместите вышеуказанную строку в самый низ-->

  <!-- Скрипт настройки Firebase тип="module"-->
  <!-- <script type="module">
    import { initializeApp } from "firebase/app";
    import { getAnalytics } from "firebase/analytics";
    const firebaseConfig = {
      apiKey: "AIzaSyBenD4UHfJiCcodpSzYKFe4buxRg_ZfZic",
      authDomain: "techcureindia.firebaseapp.com",
      projectId: "techcureindia",
      storageBucket: "techcureindia.appspot.com",
      messagingSenderId: "1016267859555",
      appId: "1:1016267859555:web:45e1e213f671b886323a56",
      measurementId: "G-VNSZL96YJM"
    };
    const app = initializeApp(firebaseConfig);
    const analytics = getAnalytics(app);
  </script> -->

  <!-- Firebase ИНИЦИАЛИЗАЦИЯ способ 2.0 -->
  <script src="https://www.gstatic.com/firebasejs/8.10.1/firebase-app.js"></script>
  <script src="https://www.gstatic.com/firebasejs/7.17.1/firebase-firestore.js"></script>
  <script src="https://www.gstatic.com/firebasejs/8.4.1/firebase-messaging.js"></script>
  <script src="https://www.gstatic.com/firebasejs/8.6.5/firebase-analytics.js"></script>
  <script src="https://maps.googleapis.com/maps/api/js?key=yourKey"></script>
  <script>

    // Конфигурация Firebase для вашего веб-приложения

    const firebaseConfig = {
      apiKey: "AIzaSyBenD4UHfJiCcodpSzYKFe4buxRg_ZfZic",
      authDomain: "techcureindia.firebaseapp.com",
      projectId: "techcureindia",
      storageBucket: "techcureindia.appspot.com",
      messagingSenderId: "1016267859555",
      appId: "1:1016267859555:web:45e1e213f671b886323a56",
      measurementId: "G-VNSZL96YJM"
    };

    /// Инициализация Firebase
    firebase.initializeApp(firebaseConfig);
    firebase.analytics();
  </script>
  <!-- Firebase ИНИЦИАЛИЗАЦИЯ способ 2.0 -->

  <!-- syncfusion-PDF -->
  <script src="//cdnjs.cloudflare.com/ajax/libs/pdf.js/2.11.338/pdf.min.js"></script>
  <script type="text/javascript">
    pdfjsLib.GlobalWorkerOptions.workerSrc = "//cdnjs.cloudflare.com/ajax/libs/pdf.js/2.11.338/pdf.worker.min.js";
  </script>

  <script>
    window.addEventListener('load', function (ev) {
      // Загрузить main.dart.js
      _flutter.loader.loadEntrypoint({
        serviceWorker: {
          serviceWorkerVersion: serviceWorkerVersion,
        },
        onEntrypointLoaded: function (engineInitializer) {
          engineInitializer.initializeEngine().then(function (appRunner) {
            appRunner.runApp();
          });
        }
      });
    });
  </script>

  <script src="main.dart.js" type="application/javascript"></script>
</body>

</html>

Если вы все еще получаете ошибку, пожалуйста, предоставьте полный файл index.html вашего проекта

Надеюсь, это поможет вам

Ответ или решение

Решение проблемы с Firebase Cloud Messaging в Flutter Web

Введение

Вы пытаетесь вызвать функцию requestPermission() из FirebaseMessaging, и, по вашим словам, она не возвращает никакого ответа, а выполнение функции останавливается. Эта проблема может возникнуть по нескольким причинам, включая неправильную настройку Firebase, ошибки в коде или конфликты в браузере. В этой статье мы рассмотрим шаги, которые могут помочь вам диагностировать и устранить проблему.

Шаги для устранения проблемы

1. Проверьте поддержку браузера

Убедитесь, что используемый вами браузер поддерживает службы фоновной обработки сообщений и FCM. Вы упомянули, что тестировали в Edge и на Android. Рекомендуется протестировать работу в Google Chrome, так как он обычно лучше поддерживает такие функции, как сервисные работники и Firebase.

2. Проверьте настройки в index.html

Файл index.html является ключевым для настройки вашего приложения Flutter Web с Firebase. Убедитесь, что ваши скрипты загружаются в правильном порядке:

<script>
    window.addEventListener('load', function (ev) {
      // Downloads the main.dart.js
      _flutter.loader.loadEntrypoint({
        serviceWorker: {
          serviceWorkerVersion: serviceWorkerVersion,
        },
        onEntrypointLoaded: function (engineInitializer) {
          engineInitializer.initializeEngine().then(function (appRunner) {
            appRunner.runApp();
          });
        }
      });
    });
</script>
<script src="main.dart.js" type="application/javascript"></script>

Этот порядок очень важен, так как скрипт, который инициирует загрузку вашего приложения, должен находиться после основного main.dart.js.

3. Структура скриптов для инициализации Firebase

Убедитесь, что вы правильно настроили скрипты для инициализации Firebase:

<script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-messaging.js"></script>
<script>
    const firebaseConfig = {
      apiKey: '...',
      appId: '...',
      messagingSenderId: '...',
      projectId: '...',
      authDomain: '...',
      storageBucket: '...',
    };
    firebase.initializeApp(firebaseConfig);
    const messaging = firebase.messaging();
</script>

Следите за порядком загрузки скриптов. Это критически важно для корректной работы вашего приложения.

4. Проверка прав доступа

Убедитесь, что ваше приложение имеет все необходимые разрешения на отправку уведомлений. В случае успешного выполнения requestPermission(), вы должны видеть изменение статуса разрешений:

final response = await fcm.requestPermission();
print(response.authorizationStatus.name);

Если вы не видите никаких изменений в консоли, это может указывать на проблему с обработкой разрешений.

5. Обработка ошибок

Добавьте дополнительные обработчики ошибок в ваш код, чтобы отследить возможные сбои:

try {
    final response = await fcm.requestPermission();
    // Проверка на специфические статусы разрешений
    if (response.authorizationStatus == AuthorizationStatus.denied) {
        throw Exception('Permission denied');
    }
} catch (e) {
    print('Error getting permissions: $e');
}
6. Сервисный работник

Убедитесь, что вы зарегистрировали сервисный работник в вашем index.html:

if ('serviceWorker' in navigator) {
    window.addEventListener('load', function() {
        navigator.serviceWorker.register('/firebase-messaging-sw.js')
            .then(function(registration) {
                console.log('ServiceWorker registration successful with scope: ', registration.scope);
            })
            .catch(function(err) {
                console.log('ServiceWorker registration failed: ', err);
            });
    });
}

Это необходимо для обеспечения поддержки фоновых уведомлений.

Заключение

Если все вышеперечисленные шаги не помогли решить вашу проблему, возможно, стоит рассмотреть возможность создания нового проекта или проверки работоспособности на другом устройстве или конфигурации. Убедитесь, что все зависимости и версии пакетов, указанные в pubspec.yaml, актуальны. Используйте flutter upgrade для обновления Flutter до последней версии.

Проблема может быть сложной и многогранной, поэтому будьте терпеливы и систематично подходите к ее разрешению. Если у вас останутся вопросы, не стесняйтесь делиться ими!

Оцените материал
Добавить комментарий

Капча загружается...