Вопрос или проблема
Невозможно перенаправить на определённую страницу при нажатии на уведомление в 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}');
}
Проблема
-
Перенаправление не работает: Когда я нажимаю на уведомление, оно не перенаправляет меня на страницу RedeemCode. navigatorKey определен глобально в main.dart, но, похоже, currentState недоступен или не работает как ожидалось.
-
Обработка данных: Полученные данные действительно содержат ожидаемый URL для перенаправления. Однако логика перенаправления, похоже, не срабатывает.
Что я пробовал
- Убедился, что navigatorKey правильно определен и доступен.
- Проверил, что формат данных из уведомления соответствует тому, что я пытаюсь декодировать.
- Добавил операторы print, чтобы проверить, срабатывает ли обработчик нажатия на уведомление.
Нужна помощь?
Я был бы признателен за любые рекомендации по отладке этой проблемы или за любые предложения о том, что я мог упустить в своей реализации. Спасибо!
Я был бы признателен за любые рекомендации по отладке этой проблемы или за любые предложения о том, что я мог упустить в своей реализации. Спасибо!
Ответ или решение
Конечно! Давайте детально разберем вашу проблему и предложим решение для корректной обработки нажатия на уведомление в Flutter с использованием Firebase Cloud Messaging (FCM).
Проблема
На данный момент вы пытаетесь перенаправить пользователя на определенную страницу (RedeemCode
) при нажатии на уведомление. Однако вы сталкиваетесь с двумя основными проблемами:
- Перенаправление не происходит, так как
navigatorKey.currentState
недоступен. - Логика обработки полезной нагрузки (
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
. Если проблема останется, проанализируйте журнал отладки на наличие ошибок, связанных с навигацией или форматом полезной нагрузки.
Если возникнут дополнительные вопросы или понадобятся уточнения, не стесняйтесь обращаться! Успехов в разработке вашего приложения!