未处理的异常:NoSuchMethodError:在 null 上调用了方法“toRawHandle”

Har*_*nta 10 android flutter firebase-cloud-messaging

我在我的 Flutter 应用程序中使用firebase_messaging库进行 Firebase 推送通知。

目前我的 firebase_messaging 版本是firebase_messaging: ^5.1.5最近更新的最新版本。

我正在尝试在后台以及应用程序终止时接收通知。

我已经按照 firebase_messaging 文档中提到的所有步骤进行了操作,但不幸的是,我在 flutter 中遇到了上述错误。

这是我在 dart 中的通知处理程序类

通知处理程序.dart

import 'dart:async';
import 'dart:io';
import 'dart:math';

import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:path_provider/path_provider.dart';
import 'package:http/http.dart' as http;

class NotificationHandler {
  FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;
  FirebaseMessaging _fcm = FirebaseMessaging();
  StreamSubscription iosSubscription;
  static final NotificationHandler _singleton =
      new NotificationHandler._internal();

  factory NotificationHandler() {
    return _singleton;
  }
  NotificationHandler._internal();

  Future<dynamic> myBackgroundMessageHandler(
      Map<String, dynamic> message) async {
    print("onLaunch: $message");
    _showBigPictureNotification(message);
    // Or do other work.
  }

  initializeFcmNotification() async {
    flutterLocalNotificationsPlugin = new FlutterLocalNotificationsPlugin();

    var initializationSettingsAndroid =
        new AndroidInitializationSettings('ic_launcher');
    var initializationSettingsIOS = new IOSInitializationSettings(
        onDidReceiveLocalNotification: onDidReceiveLocalNotification);
    var initializationSettings = new InitializationSettings(
        initializationSettingsAndroid, initializationSettingsIOS);
    flutterLocalNotificationsPlugin.initialize(initializationSettings,
        onSelectNotification: onSelectNotification);

    if (Platform.isIOS) {
      iosSubscription = _fcm.onIosSettingsRegistered.listen((data) {
        // save the token  OR subscribe to a topic here
      });

      _fcm.requestNotificationPermissions(IosNotificationSettings());
    } else {
      _saveDeviceToken();
    }

    _fcm.configure(
      onMessage: (Map<String, dynamic> message) async {
        print("onMessage: $message");
        _showBigPictureNotification(message);
      },
      onBackgroundMessage: myBackgroundMessageHandler,
      onLaunch: (Map<String, dynamic> message) async {
        print("onLaunch: $message");
      },
      onResume: (Map<String, dynamic> message) async {
        print("onResume: $message");
      },
    );
  }

  /// Get the token, save it to the database for current user
  _saveDeviceToken() async {
    String fcmToken = await _fcm.getToken();
    print("FCM_TOKEN: $fcmToken");
  }

  Future<void> _showBigPictureNotification(message) async {
    var rng = new Random();
    var notifId = rng.nextInt(100);

    var largeIconPath = await _downloadAndSaveImage(
        'https://cdn.pixabay.com/photo/2019/04/21/21/29/pattern-4145023_960_720.jpg',
        'largeIcon');
    var bigPicturePath = await _downloadAndSaveImage(
        'https://cdn.pixabay.com/photo/2019/04/21/21/29/pattern-4145023_960_720.jpg',
        'bigPicture');
    var bigPictureStyleInformation = BigPictureStyleInformation(
        bigPicturePath, BitmapSource.FilePath,
        largeIcon: largeIconPath,
        largeIconBitmapSource: BitmapSource.FilePath,
        contentTitle: message['data']['title'],
        htmlFormatContentTitle: true,
        summaryText: message['data']['body'],
        htmlFormatSummaryText: true);
    var androidPlatformChannelSpecifics = AndroidNotificationDetails(
        '12', 'trading_id', message['data']['body'],
        importance: Importance.High,
        priority: Priority.High,
        style: AndroidNotificationStyle.BigPicture,
        styleInformation: bigPictureStyleInformation);
    var platformChannelSpecifics =
        NotificationDetails(androidPlatformChannelSpecifics, null);
    await flutterLocalNotificationsPlugin.show(
        notifId,
        message['data']['title'],
        message['data']['body'],
        platformChannelSpecifics,
        payload: message['data']['body']);
  }

  Future<void> _showBigTextNotification(message) async {
    var rng = new Random();
    var notifId = rng.nextInt(100);
    var bigTextStyleInformation = BigTextStyleInformation(
        message['data']['body'],
        htmlFormatBigText: true,
        contentTitle: message['data']['title'],
        htmlFormatContentTitle: true,
        summaryText: message['data']['body'],
        htmlFormatSummaryText: true);
    var androidPlatformChannelSpecifics = AndroidNotificationDetails(
        '12', 'trading_id', '',
        importance: Importance.High,
        priority: Priority.High,
        style: AndroidNotificationStyle.BigText,
        styleInformation: bigTextStyleInformation);
    var platformChannelSpecifics =
        NotificationDetails(androidPlatformChannelSpecifics, null);
    await flutterLocalNotificationsPlugin.show(
        notifId,
        message['data']['title'],
        message['data']['body'],
        platformChannelSpecifics,
        payload: message['data']['body']);
  }

  Future onSelectNotification(String payload) async {
    if (payload != null) {
      debugPrint('notification payload: ' + payload);
    }
    // await Navigator.push(
    //   context,
    //   new MaterialPageRoute(builder: (context) => new SecondScreen(payload)),
    // );
  }

  Future<void> onDidReceiveLocalNotification(
      int id, String title, String body, String payload) async {
    // display a dialog with the notification details, tap ok to go to another page
  }

  Future<String> _downloadAndSaveImage(String url, String fileName) async {
    var directory = await getApplicationDocumentsDirectory();
    var filePath = '${directory.path}/$fileName';
    var response = await http.get(url);
    var file = File(filePath);
    await file.writeAsBytes(response.bodyBytes);
    return filePath;
  }
}
Run Code Online (Sandbox Code Playgroud)

我在主屏幕上这样称呼它

   @override
  void initState() {
    // TODO: implement initState
    super.initState();
    new NotificationHandler().initializeFcmNotification();
  }
Run Code Online (Sandbox Code Playgroud)

Koh*_*hls 8

编辑1:

冲浪了几个git线程和stackoverflow线程,终于找到了一个没人能说出的最短答案:

“只需将处理程序放在全局范围内”

在您的whatever.dart 文件中,只需将 _firebaseMessaging 和 4 个处理程序、onMessage、onLaunch 等放在本地类之外,瞧!没有崩溃!


原来的:

我使用了bkmza 答案,但不是跨平台的OP 修复

出于某种原因,设置

void initState() {
super.initState();
    _firebaseMessaging.configure
}
Run Code Online (Sandbox Code Playgroud)

不工作,然后我尝试

Future.delayed(Duration(seconds: 1), () {
     _firebaseMessaging.configure
    }
);
Run Code Online (Sandbox Code Playgroud)

我让它完美地工作:)

也许 FCM 初始化尚未准备好配置处理程序,在 Firebase Core 完全加载后设置延迟使其正常工作


Pet*_*ein 5

当我使用 onBackgroundMessage 时,应用程序出现错误或崩溃。

我的 Firebase Messaging 实现

主程序.dart

initState(){
  ....
  HelperClass.initFCM(some dependencies);
}
Run Code Online (Sandbox Code Playgroud)

helperClass.dart

class HelperClass
{
final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();

Future<dynamic> backgroundMessageHandler(Map<String, dynamic> message) {
  print("_backgroundMessageHandler");
  if (message.containsKey('data')) {
    // Handle data message
    final dynamic data = message['data'];
    print("_backgroundMessageHandler data: ${data}");
  }

  if (message.containsKey('notification')) {
    // Handle notification message
    final dynamic notification = message['notification'];
    print("_backgroundMessageHandler notification: ${notification}");
  }

  Future<void> initFCM(...){
    _firebaseMessaging.configure(
      .....,
      onBackgroundMessage: backgroundMessageHandler,
      .....
      );
  }
}
Run Code Online (Sandbox Code Playgroud)

我无法在 main.dart 中配置 firebase,因为我对此有一些逻辑。例如,我仅在用户登录时才初始化 FCM,等等。所以我必须在类中配置 firebase。

启动应用程序时,我遇到了 ToRawHandle() 错误

E/flutter (23610): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: NoSuchMethodError: The method 'toRawHandle' was called on null.
E/flutter (23610): Receiver: null
E/flutter (23610): Tried calling: toRawHandle()
E/flutter (23610): #0      Object.noSuchMethod  (dart:core-patch/object_patch.dart:51:5)
E/flutter (23610): #1      FirebaseMessaging.configure 
package:firebase_messaging/firebase_messaging.dart:12
Run Code Online (Sandbox Code Playgroud)

当我像这样将函数设置为STATIC时

static Future<dynamic> backgroundMessageHandler(Map<String, dynamic> message) {
      print("_backgroundMessageHandler");
      if (message.containsKey('data')) {
        // Handle data message
        final dynamic data = message['data'];
        print("_backgroundMessageHandler data: ${data}");
      }

      if (message.containsKey('notification')) {
        // Handle notification message
        final dynamic notification = message['notification'];
        print("_backgroundMessageHandler notification: ${notification}");
      }
Run Code Online (Sandbox Code Playgroud)

配置firebase时APP崩溃

uid: 10532
signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr --------
    x0  0000000000000000  x1  0000000000005fda  x2  0000000000000006  x3  00000077dc702860
    x4  00000077dc702740  x5  00000077dc702740  x6  00000077dc702740  x7  0000000000000000
    x8  00000000000000f0  x9  204a59b65fcacfed  x10 fffffff0fffffbdf  x11 0000000000000000
    x12 0000000000000000  x13 0000000000000010  x14 0000000000000020  x15 00000077dc702740
    x16 00000078d0ef68b8  x17 00000078d0ed4710  x18 00000077cd1e8000  x19 00000000000000ac
    x20 0000000000005f77  x21 00000000000000b2  x22 0000000000005fda  x23 00000000ffffffff
    x24 000000000000003a  x25 00000077dc703020  x26 000000000000003a  x27 0000000000000001
    x28 0000000000000001  x29 00000077dc702910
    sp  00000077dc702840  lr  00000078d0e8744c  pc  00000078d0e8746c
backtrace:
      #00 pc 000000000008246c  /apex/com.android.runtime/lib64/bionic/libc.so (abort+160) (BuildId: 5812256023147338b8a9538321d4c456)
      #01 pc 00000000011c8d80  /data/app/com.kleinpetr.app-DIUNepS7D_5Cnpsb5tArzA==/lib/arm64/libflutter.so!libflutter.so (offset 0x11c0000) (BuildId: d8bf9b314511c944)
      #02 pc 00000000011d39a0  /data/app/com.kleinpetr.app-DIUNepS7D_5Cnpsb5tArzA==/lib/arm64/libflutter.so!libflutter.so (offset 0x11c0000) (BuildId: d8bf9b314511c944)
      #03 pc 00000000011d7c54  /data/app/com.kleinpetr.app-DIUNepS7D_5Cnpsb5tArzA==/lib/arm64/libflutter.so!libflutter.so (offset 0x11c0000) (BuildId: d8bf9b314511c944)
      #04 pc 00000000011cf744  /data/app/com.kleinpetr.app-DIUNepS7D_5Cnpsb5tArzA==/lib/arm64/libflutter.so!libflutter.so (offset 0x11c0000) (BuildId: d8bf9b314511c944)
      #05 pc 00000000011d5a78  /data/app/com.kleinpetr.app-DIUNepS7D_5Cnpsb5tArzA==/lib/arm64/libflutter.so!libflutter.so (offset 0x11c0000) (BuildId: d8bf9b314511c944)
      #06 pc 00000000011d6154  /data/app/com.kleinpetr.app-DIUNepS7D_5Cnpsb5tArzA==/lib/arm64/libflutter.so!libflutter.so (offset 0x11c0000) (BuildId: d8bf9b314511c944)
      #07 pc 00000000011d55b0  /data/app/com.kleinpetr.app-DIUNepS7D_5Cnpsb5tArzA==/lib/arm64/libflutter.so!libflutter.so (offset 0x11c0000) (BuildId: d8bf9b314511c944)
      #08 pc 00000000011da7c8  /data/app/com.kleinpetr.app-DIUNepS7D_5Cnpsb5tArzA==/lib/arm64/libflutter.so!libflutter.so (offset 0x11c0000) (BuildId: d8bf9b314511c944)
      #09 pc 0000000000017efc  /system/lib64/libutils.so (android::Looper::pollInner(int)+864) (BuildId: 519d0734bba3d4086a9088e9bcb201de)
      #10 pc 0000000000017afc  /system/lib64/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+56) (BuildId: 519d0734bba3d4086a9088e9bcb201de)
      #11 pc 0000000000013644  /system/lib64/libandroid.so (ALooper_pollOnce+96) (BuildId: 8ab9f24e53265b4640c6f4dd253b4b1f)
      #12 pc 00000000011da74c  /data/app/com.kleinpetr.app-DIUNepS7D_5Cnpsb5tArzA==/lib/arm64/libflutter.so!libflutter.so (offset 0x11c0000) (BuildId: d8bf9b314511c944)
      #13 pc 00000000011d54fc  /data/app/com.kleinpetr.app-DIUNepS7D_5Cnpsb5tArzA==/lib/arm64/libflutter.so!libflutter.so (offset 0x11c0000) (BuildId: d8bf9b314511c944)
      #14 pc 00000000011d86a0  /data/app/com.kleinpetr.app-DIUNepS7D_5Cnpsb5tArzA==/lib/arm64/libflutter.so!libflutter.so (offset 0x11c0000) (BuildId: d8bf9b314511c944)
      #15 pc 00000000000e372c  /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+36) (BuildId: 5812256023147338b8a9538321d4c456)
      #16 pc 0000000000084004  /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+64) (BuildId: 5812256023147338b8a9538321d4c456)
Lost connection to device.
Run Code Online (Sandbox Code Playgroud)


bkm*_*mza 4

从最新版本(5.15)开始,您必须在处理程序初始化期间设置以下委托:

onBackgroundMessage: myBackgroundMessageHandler
Run Code Online (Sandbox Code Playgroud)

请注意,您的处理程序至少应该是全局静态的,反之亦然,您将遇到另一个运行时异常。

以下是 FCM 初始化的示例:

_firebaseMessaging.configure(
  onBackgroundMessage: Theme.of(context).platform == TargetPlatform.iOS
      ? null
      : myBackgroundMessageHandler,
  onMessage: (Map<String, dynamic> message) async { },
  onResume: (Map<String, dynamic> message) async { },
  onLaunch: (Map<String, dynamic> message) async { },
);
Run Code Online (Sandbox Code Playgroud)

和处理程序模板:

Future<dynamic> myBackgroundMessageHandler(Map<String, dynamic> message) async { return Future<void>.value(); }
Run Code Online (Sandbox Code Playgroud)

官方 READM.me 已更新,您可以在此处找到有关它的一些注释。

这是一个 PR,它提供了在 Android 上处理后台通知的可能性。您可以在这里找到详细信息。