firebase消息传递在前景中崩溃

发布于 2025-02-09 04:11:23 字数 7801 浏览 0 评论 0原文

我正在开发一个带有firebase消息传递的颤音应用程序 https://pub.dev/packages/awesome_notifications )。以下是我的代码。

import 'dart:developer' as developer;

import 'package:awesome_notifications/awesome_notifications.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';

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

  await Firebase.initializeApp();
  FirebaseMessaging _messaging = FirebaseMessaging.instance;

  FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);

  //Request permission for firebase messaging

  NotificationSettings settings = await _messaging.requestPermission(
    alert: true,
    announcement: false,
    badge: true,
    carPlay: false,
    criticalAlert: false,
    provisional: false,
    sound: true,
  );

  if (settings.authorizationStatus == AuthorizationStatus.authorized) {
    print('User granted permission');

    FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
      RemoteNotification? notification = message.notification;
      AndroidNotification? android = message.notification?.android;
      print("REMOTE MESSAGE LISTENER");
      if (message.data["data_type"] == "TEXT") {
        await AwesomeNotifications().createNotification(
          content: NotificationContent(
              id: UniqueKey().hashCode,
              groupKey: message.data["senderUid"],
              channelKey: 'basic_channel',
              title: message.data["name"],
              body: message.data["body"],
              summary: message.data["body"], // Anything you want here
              notificationLayout: NotificationLayout.Messaging,
              displayOnBackground: true,
              displayOnForeground: true),
        );
      } else if (message.data["data_type"] == "IMAGE") {
        await AwesomeNotifications().createNotification(
          content: NotificationContent(
              id: UniqueKey().hashCode,
              groupKey: message.data["senderUid"],
              channelKey: 'basic_channel',
              title: message.data["name"],
              body: Emojis.art_framed_picture + " " + message.data["body"],
              summary: message.data["body"], // Anything you want here
              notificationLayout: NotificationLayout.Messaging,
              displayOnBackground: true,
              displayOnForeground: true),
        );
      }
    });
  } else {
    print('User declined or has not accepted permission');
  }

  /// Update the iOS foreground notification presentation options to allow
  /// heads up notifications.
  await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
    alert: true,
    badge: true,
    sound: true,
  );

  FirebaseMessaging.instance.getInitialMessage().then((RemoteMessage? message) {
    developer.log("REMOTE MESSAGE");
    if (message != null) {
      developer.log(message.data.toString());
    }
  });

  // For handling notification when the app is in background
  // but not terminated
  FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
    print("onMessageOpenedApp executed");
  });

  AwesomeNotifications().initialize('resource://drawable/logo', [
    NotificationChannel(
        channelGroupKey: 'basic_tests',
        channelKey: 'basic_channel',
        channelName: 'Basic notifications',
        channelDescription: 'Notification channel for basic tests',
        defaultColor: Color(0xFF9D50DD),
        ledColor: Colors.white,
        importance: NotificationImportance.High),
  ]);

  runApp( child: MyApp());
}

// Declared as global, outside of any class
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  // If you're going to use other Firebase services in the background, such as Firestore,
  // make sure you call `initializeApp` before using other Firebase services.
  await Firebase.initializeApp();
  developer.log("background listener called");
  print("Handling a background message: ${message.data}");

  // Use this method to automatically convert the push data, in case you gonna use our data standard
  //AwesomeNotifications().createNotificationFromJsonData(message.data);
  if (message.data['data_type'].toString().toUpperCase() == "TEXT") {
    print("Handling a background message: ${message.data['data_type']}");
    await AwesomeNotifications().createNotification(
      content: NotificationContent(
          id: UniqueKey().hashCode,
          groupKey: message.data["senderUid"],
          channelKey: 'basic_channel',
          title: message.data["name"],
          body: message.data["body"],
          summary: message.data["body"], // Anything you want here
          notificationLayout: NotificationLayout.Messaging,
          displayOnForeground: true,
          displayOnBackground: true),
    );
  } else if (message.data['data_type'].toString().toUpperCase() == "IMAGE") {
    await AwesomeNotifications().createNotification(
      content: NotificationContent(
          id: UniqueKey().hashCode,
          groupKey: message.data["senderUid"],
          channelKey: 'basic_channel',
          title: message.data["name"],
          body: Emojis.art_framed_picture + " " + message.data["body"],
          summary: message.data["body"], // Anything you want here
          notificationLayout: NotificationLayout.Messaging,
          displayOnBackground: true,
          displayOnForeground: true),
    );
  }
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    AwesomeNotifications()
        .actionStream
        .listen((ReceivedNotification receivedNotification) {
      developer.log("Notification clicked");
      developer.log(receivedNotification.body ?? "no data");
    });

    return MaterialApp(
        title: 'Flutter Demo',
        debugShowCheckedModeBanner: false,
        home: LoadingScreen()); // LoginLanguageSelectScreen());
  }
}

以下是我的 appdelegate

import UIKit
import Flutter
import GoogleMaps

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
      if #available(iOS 10.0, *) {
        UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
      }
      application.registerForRemoteNotifications()
      GMSServices.provideAPIKey("xxxx-xxxx")
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

我的代码在Android和iOS中正常工作。但是,在前景中执行通知时,该应用程序会以以下错误崩溃。这仅在iOS 中发生

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x16f793ff8)
    frame #0: 0x0000000188cfd7dc libswiftCore.dylib`swift_conformsToProtocolMaybeInstantiateSuperclasses(swift::TargetMetadata<swift::InProcess> const*, swift::TargetProtocolDescriptor<swift::InProcess> const*, bool) + 44
libswiftCore.dylib`swift_conformsToProtocolMaybeInstantiateSuperclasses:
->  0x188cfd7dc <+44>: str    w2, [sp, #0x68]
    0x188cfd7e0 <+48>: strb   w2, [sp, #0x77]
    0x188cfd7e4 <+52>: adrp   x22, 445806
    0x188cfd7e8 <+56>: ldr    x8, [x22, #0x5a0]
Target 0: (Runner) stopped.

这发生在firebasemessaging.onmessage.listen lietener中。如果我从那里删除很棒的通知代码,则可以正常工作。

这里有什么问题以及如何解决?

I am developing a Flutter app with Firebase Messaging and Awesome Notifications (https://pub.dev/packages/awesome_notifications). Below is my code.

import 'dart:developer' as developer;

import 'package:awesome_notifications/awesome_notifications.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';

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

  await Firebase.initializeApp();
  FirebaseMessaging _messaging = FirebaseMessaging.instance;

  FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);

  //Request permission for firebase messaging

  NotificationSettings settings = await _messaging.requestPermission(
    alert: true,
    announcement: false,
    badge: true,
    carPlay: false,
    criticalAlert: false,
    provisional: false,
    sound: true,
  );

  if (settings.authorizationStatus == AuthorizationStatus.authorized) {
    print('User granted permission');

    FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
      RemoteNotification? notification = message.notification;
      AndroidNotification? android = message.notification?.android;
      print("REMOTE MESSAGE LISTENER");
      if (message.data["data_type"] == "TEXT") {
        await AwesomeNotifications().createNotification(
          content: NotificationContent(
              id: UniqueKey().hashCode,
              groupKey: message.data["senderUid"],
              channelKey: 'basic_channel',
              title: message.data["name"],
              body: message.data["body"],
              summary: message.data["body"], // Anything you want here
              notificationLayout: NotificationLayout.Messaging,
              displayOnBackground: true,
              displayOnForeground: true),
        );
      } else if (message.data["data_type"] == "IMAGE") {
        await AwesomeNotifications().createNotification(
          content: NotificationContent(
              id: UniqueKey().hashCode,
              groupKey: message.data["senderUid"],
              channelKey: 'basic_channel',
              title: message.data["name"],
              body: Emojis.art_framed_picture + " " + message.data["body"],
              summary: message.data["body"], // Anything you want here
              notificationLayout: NotificationLayout.Messaging,
              displayOnBackground: true,
              displayOnForeground: true),
        );
      }
    });
  } else {
    print('User declined or has not accepted permission');
  }

  /// Update the iOS foreground notification presentation options to allow
  /// heads up notifications.
  await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
    alert: true,
    badge: true,
    sound: true,
  );

  FirebaseMessaging.instance.getInitialMessage().then((RemoteMessage? message) {
    developer.log("REMOTE MESSAGE");
    if (message != null) {
      developer.log(message.data.toString());
    }
  });

  // For handling notification when the app is in background
  // but not terminated
  FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
    print("onMessageOpenedApp executed");
  });

  AwesomeNotifications().initialize('resource://drawable/logo', [
    NotificationChannel(
        channelGroupKey: 'basic_tests',
        channelKey: 'basic_channel',
        channelName: 'Basic notifications',
        channelDescription: 'Notification channel for basic tests',
        defaultColor: Color(0xFF9D50DD),
        ledColor: Colors.white,
        importance: NotificationImportance.High),
  ]);

  runApp( child: MyApp());
}

// Declared as global, outside of any class
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  // If you're going to use other Firebase services in the background, such as Firestore,
  // make sure you call `initializeApp` before using other Firebase services.
  await Firebase.initializeApp();
  developer.log("background listener called");
  print("Handling a background message: ${message.data}");

  // Use this method to automatically convert the push data, in case you gonna use our data standard
  //AwesomeNotifications().createNotificationFromJsonData(message.data);
  if (message.data['data_type'].toString().toUpperCase() == "TEXT") {
    print("Handling a background message: ${message.data['data_type']}");
    await AwesomeNotifications().createNotification(
      content: NotificationContent(
          id: UniqueKey().hashCode,
          groupKey: message.data["senderUid"],
          channelKey: 'basic_channel',
          title: message.data["name"],
          body: message.data["body"],
          summary: message.data["body"], // Anything you want here
          notificationLayout: NotificationLayout.Messaging,
          displayOnForeground: true,
          displayOnBackground: true),
    );
  } else if (message.data['data_type'].toString().toUpperCase() == "IMAGE") {
    await AwesomeNotifications().createNotification(
      content: NotificationContent(
          id: UniqueKey().hashCode,
          groupKey: message.data["senderUid"],
          channelKey: 'basic_channel',
          title: message.data["name"],
          body: Emojis.art_framed_picture + " " + message.data["body"],
          summary: message.data["body"], // Anything you want here
          notificationLayout: NotificationLayout.Messaging,
          displayOnBackground: true,
          displayOnForeground: true),
    );
  }
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    AwesomeNotifications()
        .actionStream
        .listen((ReceivedNotification receivedNotification) {
      developer.log("Notification clicked");
      developer.log(receivedNotification.body ?? "no data");
    });

    return MaterialApp(
        title: 'Flutter Demo',
        debugShowCheckedModeBanner: false,
        home: LoadingScreen()); // LoginLanguageSelectScreen());
  }
}

Below is my AppDelegate

import UIKit
import Flutter
import GoogleMaps

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
      if #available(iOS 10.0, *) {
        UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
      }
      application.registerForRemoteNotifications()
      GMSServices.provideAPIKey("xxxx-xxxx")
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

My code is working fine in Android and iOS. However when it comes to executing notifications in foreground, the app crashes with the following error. This happens only in iOS.

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x16f793ff8)
    frame #0: 0x0000000188cfd7dc libswiftCore.dylib`swift_conformsToProtocolMaybeInstantiateSuperclasses(swift::TargetMetadata<swift::InProcess> const*, swift::TargetProtocolDescriptor<swift::InProcess> const*, bool) + 44
libswiftCore.dylib`swift_conformsToProtocolMaybeInstantiateSuperclasses:
->  0x188cfd7dc <+44>: str    w2, [sp, #0x68]
    0x188cfd7e0 <+48>: strb   w2, [sp, #0x77]
    0x188cfd7e4 <+52>: adrp   x22, 445806
    0x188cfd7e8 <+56>: ldr    x8, [x22, #0x5a0]
Target 0: (Runner) stopped.

This happens in FirebaseMessaging.onMessage.listen lietener. If I remove the Awesome Notifications code from there, it works fine.

What is the issue here and how to fix it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文