后台通知栏重复通知

问题描述 投票:0回答:1

我正在致力于在 Flutter 中使用 FCM 和 flutter_local_notifications 实现推送通知。我目前只在 Android 上进行测试。通知在前台工作正常,但是当应用程序在后台时,我只收到一次通知,但它在通知栏中显示重复。

这是我的 AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <application
        android:label="flutter_weather"
        android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher">
        <activity
            android:name=".MainActivity"
            android:showWhenLocked="true"
            android:turnScreenOn="true"
            android:exported="true"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <!-- Specifies an Android theme to apply to this Activity as soon as
                 the Android process has started. This theme is visible to the user
                 while the Flutter UI initializes. After that, this theme continues
                 to determine the Window background behind the Flutter UI. -->
            <meta-data
              android:name="io.flutter.embedding.android.NormalTheme"
              android:resource="@style/NormalTheme"
              />
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
            <intent-filter>
                <action android:name="FLUTTER_NOTIFICATION_CLICK"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
                <meta-data
           android:name="firebase_messaging_auto_init_enabled"
           android:value="false" />
    </application>
</manifest>

这是我的

main.dart

import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:flutter_native_splash/flutter_native_splash.dart';
import 'package:flutter_weather/firebase_options.dart';
import 'package:flutter_weather/screens/notification_screen.dart';
import 'package:flutter_weather/screens/test_screen.dart';

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

class WeatherApp extends StatefulWidget {
  const WeatherApp({super.key});

  @override
  createState() => _WeatherAppState();
}

@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  await setupFlutterNotifications(); // setting method
  showFlutterNotification(message); // local notification
}

// FCM foreground processing - Show local notification
void showFlutterNotification(RemoteMessage message) {
  RemoteNotification? notification = message.notification;

  AndroidNotification? android = message.notification?.android;

  if (notification != null && android != null) {
    flutterLocalNotificationsPlugin.show(
      0,
      notification.title,
      notification.body,
      NotificationDetails(
        android: AndroidNotificationDetails(
          channel.id,
          channel.name,
          channelDescription: channel.description,
          icon: '',
        ),
      ),
      payload: message.data["screen"],
    );
  }
}

late FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;
late AndroidNotificationChannel channel;
bool isFlutterLocalNotificationsInitialized = false; 

// setting method
Future<void> setupFlutterNotifications() async {
  if (isFlutterLocalNotificationsInitialized) {
    return;
  }
  channel = const AndroidNotificationChannel(
    'high_importance_channel', // id
    'High Importance Notifications', // title
    description:
        'This channel is used for important notifications.', // description
    importance: Importance.high,
  );
  flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();

  await flutterLocalNotificationsPlugin.initialize(
    const InitializationSettings(
      android: AndroidInitializationSettings("@mipmap/ic_launcher"),
      iOS: DarwinInitializationSettings(),
    ),
    onDidReceiveNotificationResponse: onTabNotification,
    onDidReceiveBackgroundNotificationResponse: onTabNotification,
  );

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


  await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
    alert: true,
    badge: true,
    sound: true,
  );

  await FirebaseMessaging.instance.requestPermission(
    alert: true,
    announcement: false,
    badge: true,
    carPlay: false,
    criticalAlert: false,
    provisional: false,
    sound: true,
  );
  getToken();

  isFlutterLocalNotificationsInitialized = true;
}

// Function to navigate when notification is clicked
void onTabNotification(NotificationResponse details) async {
  if (details.payload != null) {
    print('onDidReceiveNotificationResponse - payload: ${details.payload}');
    navigatorKey.currentState?.pushNamed("/${details.payload}");
  }
}


Future<void> getToken() async {
  // ios
  String? token;
  if (defaultTargetPlatform == TargetPlatform.iOS ||
      defaultTargetPlatform == TargetPlatform.macOS) {
    token = await FirebaseMessaging.instance.getAPNSToken();
  }
  // aos
  else {
    token = await FirebaseMessaging.instance.getToken();
  }
  print("Token: $token");
}

void handleMessage(RemoteMessage? message) {
  // navigate to new screen when message is received and user tabs notification
  if (message != null) {
    navigatorKey.currentState?.pushNamed(
      "/${message.data["screen"]}",
      arguments: message,
    );
  }
}

void main() async {
  await dotenv.load(fileName: ".env");
  WidgetsBinding widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
  FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
  await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
  await setupFlutterNotifications();
  FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);

  runApp(const WeatherApp());
}

class _WeatherAppState extends State<WeatherApp> {
  @override
  void initState() {
    super.initState();
    FirebaseMessaging.onMessage.listen(showFlutterNotification);
    FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
    FirebaseMessaging.onMessageOpenedApp.listen(handleMessage);
    FirebaseMessaging.instance.getInitialMessage().then(handleMessage);
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "title",
      initialRoute: "/",
      routes: {
        "/notification_screen": (context) => const NotificationPage(),
      },
      navigatorKey: navigatorKey,
      home: const TestScreen(),
    );
  }
}

这是我的 JSON:

{
"notification": {"title": "background ",
"body" : "background test 123123", "alert":"true},
"priority": "high",
"data": {
"type": "notification",
"click_action": "FLUTTER_NOTIFICATION_CLICK", "screen": "notification_screen",
    "id": "1"},
    "to": "MY_DEVICE_TOKEN"
}

这个问题似乎与我如何处理

_firebaseMessagingBackgroundHandler
中的后台消息以及
setupFlutterNotifications
中通知渠道的设置有关。我尝试了各种解决方案,但问题仍然存在。

我遇到了删除“通知”字段的建议,所以我尝试了,但没有成功。

flutter firebase-cloud-messaging flutter-local-notification
1个回答
0
投票

我想是因为这条线

 showFlutterNotification(message);

这意味着您将显示该消息两次。一次 FCM,再次通过本地通知

© www.soinside.com 2019 - 2024. All rights reserved.