Обратный вызов уведомления Flutter FCM onTap не работает, когда приложение находится на переднем плане, работает в фоновAndroid

Форум для тех, кто программирует под Android
Anonymous
Обратный вызов уведомления Flutter FCM onTap не работает, когда приложение находится на переднем плане, работает в фонов

Сообщение Anonymous »

Я работаю над push-уведомлениями Flutter с использованием Firebase Cloud Messaging и локальных уведомлений.
Проблема в следующем:
  • Когда приложение находится в фоновом режиме или завершено, нажатие на уведомление работает правильно.
  • Но когда приложение уже работает на переднем плане, я получает уведомление, но нажатие на него ничего не дает.
  • Мои операторы журнала/печати внутри обратного вызова касания не распечатываются.
Я показываю уведомления вручную, когда приложение находится на переднем плане.
Текущее поведение
Передний план
  • Появляется уведомление
  • Обратный вызов при нажатии НЕ срабатывает
  • Печать/журнал не выполняется
Фон
  • Уведомление появляется
  • Обратный вызов при нажатии работает правильно
Пакеты Flutter
firebase_messaging:
flutter_local_notifications:

Полезная нагрузка Firebase из серверной части
{
"message": {
"token": "DEVICE_TOKEN",
"notification": {
"title": "Test Title",
"body": "Test Body"
},
"data": {
"type": "chat",
"id": "123",
"taks_id: "123",
"taskable_id: "123"
}
}
}

import 'dart:convert';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:mre/utils/notification_router.dart';

final class LocalNotificationHelper {
static final FlutterLocalNotificationsPlugin _plugin =
FlutterLocalNotificationsPlugin();

static Future init() async {
const android = AndroidInitializationSettings('@mipmap/retiq');
const ios = DarwinInitializationSettings();

const settings = InitializationSettings(android: android, iOS: ios);

await _plugin.initialize(
settings,
onDidReceiveNotificationResponse: (response) {
if (response.payload != null) {
final data = jsonDecode(response.payload!);
NotificationRouter.handle(data);
}
},
);

await _createChannels();
}

static Future _createChannels() async {
const channel = AndroidNotificationChannel(
'high_importance_channel', 'High Importance Notifications',
importance: Importance.high,
enableLights: true,
sound: RawResourceAndroidNotificationSound("notification"));

await _plugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
}

static Future showNotification(RemoteMessage message) async {
final data = message.data;

final title = data['title'] ?? message.notification?.title;
final body = data['body'] ?? message.notification?.body;

final androidDetails = AndroidNotificationDetails(
'high_importance_channel',
'High Importance Notifications',
importance: Importance.high,
priority: Priority.high,
);

const iosDetails = DarwinNotificationDetails();

await _plugin.show(
DateTime.now().microsecond,
title,
body,
NotificationDetails(
android: androidDetails,
iOS: iosDetails,
),
payload: jsonEncode(data),
);
}
}

import 'dart:convert';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:mre/utils/notification_helper.dart';
import 'package:mre/utils/notification_router.dart';

class NotificationService {
static final FirebaseMessaging _messaging = FirebaseMessaging.instance;

static String? _lastHandledMessageId;

static Future init() async {
await _requestPermission();

/// Foreground messages
FirebaseMessaging.onMessage.listen(_onForegroundMessage);

/// App opened from background
FirebaseMessaging.onMessageOpenedApp.listen(_onMessageOpened);

/// App opened from terminated state
final initialMessage = await _messaging.getInitialMessage();
if (initialMessage != null) {
_handleNavigation(initialMessage);
}
}

static Future _requestPermission() async {
await _messaging.requestPermission(
alert: true,
badge: true,
sound: true,
);
}

/// Foreground → show local notification
static void _onForegroundMessage(RemoteMessage message) {
LocalNotificationHelper.showNotification(message);
}

/// Background tap
static void _onMessageOpened(RemoteMessage message) {
_handleNavigation(message);
}

/// Navigation handler (DEDUPLICATED)
static void _handleNavigation(RemoteMessage message) {
final messageId = message.messageId ?? jsonEncode(message.data);

if (_lastHandledMessageId == messageId) return;

_lastHandledMessageId = messageId;

NotificationRouter.handle(message.data);
}
}

import 'package:flutter/material.dart';
import 'package:mre/screens/opn_form/view/opn_form_view.dart';
import '../core/mk_route.dart';
import "../utils/context.dart";

class NotificationRouter {
static void handle(Map data) {
final context = GlobalContext.instance.navigatorKey?.currentContext;

if (context == null) return;

final type = data['type'] ?? "";

switch (type) {

case 'POS_ACCESS_REQUEST':
Navigator.pushNamed(context, RoutePage.accessRequest);
break;
case 'TASK':
Navigator.of(context).push(MaterialPageRoute(
builder: (context) {
return OpnFormScreen(
taskableId: data["taskable_id"],
taskId: data['task_id'],
);
},
));
break;
}
}
}

Future main() async {
WidgetsFlutterBinding.ensureInitialized();

/// Disable rotation
if (Platform.isIOS || Platform.isAndroid) {
SystemChrome.setPreferredOrientations(
[DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);
}
runApp(AppRoot());
_initializeAsync();
}

void _initializeAsync() async {
await FirebaseIntegration().invoke();
await Future.wait([
CrashlyticsIntegration().invoke(),
UpGraderIntegration().invoke(),
LocalNotificationHelper.init(),
NotificationService.init()
]);
_requestLocationPermission();
}

Вернуться в «Android»