Невозможно перенаправить на определённую страницу при нажатии на уведомление в Flutter Firebase Messaging

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

Невозможно перенаправить на определённую страницу при нажатии на уведомление в Flutter Firebase Messaging

Я работаю над приложением на Flutter, которое использует Firebase Cloud Messaging (FCM) для push-уведомлений. Я реализовал обработчик уведомлений, чтобы перенаправлять пользователя на конкретную страницу при нажатии на уведомление. Однако перенаправление не работает должным образом.

Фрагмент кода
Вот мой класс Messaging, отвечающий за обработку уведомлений:

import 'dart:convert';

import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';

import '../../main.dart';
import '../../view/redeem_code/redeem_code.dart';

class Messaging {
  static final Messaging _instance = Messaging._internal();
  static FlutterLocalNotificationsPlugin? flutterLocalNotificationsPlugin;
  static AndroidNotificationChannel? channel;
  static late FirebaseMessaging messaging;

  Messaging._internal();

  factory Messaging() => _instance;

  static Future initialize() async {
    messaging = FirebaseMessaging.instance;
    flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
    await createNotificationChannel();
    await setupForegroundMessaging();
    FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
  }

  static Future createNotificationChannel() async {
    channel = const AndroidNotificationChannel(
      'high_importance_channel',
      'Высокая важность уведомлений',
      description: 'Этот канал используется для важных уведомлений.',
      importance: Importance.high,
    );
    await flutterLocalNotificationsPlugin!
        .resolvePlatformSpecificImplementation<
            AndroidFlutterLocalNotificationsPlugin>()
        ?.createNotificationChannel(channel!);
  }

  static Future setupForegroundMessaging() async {
    const android = AndroidInitializationSettings('@mipmap/ic_launcher');
    const iOS = DarwinInitializationSettings();
    const initSettings = InitializationSettings(android: android, iOS: iOS);

    await flutterLocalNotificationsPlugin!.initialize(
      initSettings,
      onDidReceiveNotificationResponse: notificationTapBackground,
      onDidReceiveBackgroundNotificationResponse: notificationTapBackground,
    );

    FirebaseMessaging.onMessage.listen((RemoteMessage message) {
      if (message.notification != null) {
        flutterLocalNotificationsPlugin!.show(
          message.hashCode,
          message.notification!.title,
          message.notification!.body,
          NotificationDetails(
            android: AndroidNotificationDetails(
              channel!.id,
              channel!.name,
              channelDescription: channel!.description,
              importance: Importance.max,
              priority: Priority.high,
            ),
          ),
        );
      }
    });

    await messaging.setForegroundNotificationPresentationOptions(
      alert: true,
      badge: true,
      sound: true,
    );
  }

  static Future getFCM() async {
    final fcmToken = await messaging.getToken();
    return fcmToken;
  }
}

Future _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  await Firebase.initializeApp();
  print("Обработка фонового сообщения: ${message.messageId}");
}

void notificationTapBackground(NotificationResponse notificationResponse) {
  final message = notificationResponse.payload;
  if (message != null && message.isNotEmpty) {
    var data = jsonDecode(message);
    var redirect = data["redirect"];
    if (redirect == "redeemcode") {
      navigatorKey.currentState?.push(MaterialPageRoute(
        builder: (context) => const RedeemCode(),
      ));
    }
  }
  print(
      'Действие уведомления нажато: ${notificationResponse.actionId} с данными: ${notificationResponse.payload}');
}

Проблема

  1. Перенаправление не работает: Когда я нажимаю на уведомление, оно не перенаправляет меня на страницу RedeemCode. navigatorKey определен глобально в main.dart, но, похоже, currentState недоступен или не работает как ожидалось.

  2. Обработка данных: Полученные данные действительно содержат ожидаемый URL для перенаправления. Однако логика перенаправления, похоже, не срабатывает.

Что я пробовал

  1. Убедился, что navigatorKey правильно определен и доступен.
  2. Проверил, что формат данных из уведомления соответствует тому, что я пытаюсь декодировать.
  3. Добавил операторы print, чтобы проверить, срабатывает ли обработчик нажатия на уведомление.

Нужна помощь?
Я был бы признателен за любые рекомендации по отладке этой проблемы или за любые предложения о том, что я мог упустить в своей реализации. Спасибо!

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

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

Конечно! Давайте детально разберем вашу проблему и предложим решение для корректной обработки нажатия на уведомление в Flutter с использованием Firebase Cloud Messaging (FCM).

Проблема

На данный момент вы пытаетесь перенаправить пользователя на определенную страницу (RedeemCode) при нажатии на уведомление. Однако вы сталкиваетесь с двумя основными проблемами:

  1. Перенаправление не происходит, так как navigatorKey.currentState недоступен.
  2. Логика обработки полезной нагрузки (payload) не выполняется.

Решение

1. Переопределение глобального ключа навигации

Убедитесь, что ваш ключ навигации правильно инициализирован и доступен везде в приложении. Вы можете определить его в main.dart, например так:

import 'package:flutter/material.dart';

final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      navigatorKey: navigatorKey,
      home: HomePage(),
    );
  }
}

Убедитесь, что navigatorKey передан в аргумент navigatorKey вашего приложения.

2. Обработка нажатия на уведомление

В вашем методе notificationTapBackground необходимо убедиться, что отработал правильно механизм навигации. Вы можете использовать WidgetsBinding.instance.addPostFrameCallback, чтобы гарантировать выполнение кода после построения виджета:

void notificationTapBackground(NotificationResponse notificationResponse) {
  final String? message = notificationResponse.payload; // Измените тип payload согласно вашим данным
  if (message != null && message.isNotEmpty) {
    var data = jsonDecode(message);
    var redirect = data["redirect"];
    if (redirect == "redeemcode") {
      WidgetsBinding.instance.addPostFrameCallback((_) {
        navigatorKey.currentState?.push(MaterialPageRoute(
          builder: (context) => const RedeemCode(),
        ));
      });
    }
  }
  print(
      'Notification action tapped: ${notificationResponse.actionId} with payload: ${notificationResponse.payload}');
}

Такой подход позволяет гарантировать, что вы переходите на нужную страницу после обработки всех исследований и построений виджетов.

3. Верificaция полезной нагрузки

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

Заключение

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

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

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

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