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

Posted

技术标签:

【中文标题】未处理的异常:NoSuchMethodError:在 null 上调用了方法“toRawHandle”【英文标题】:Unhandled Exception: NoSuchMethodError: The method 'toRawHandle' was called on null 【发布时间】:2020-01-11 01:17:26 【问题描述】:

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

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

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

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

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

notification_handler.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;
  

我在主屏幕上这样称呼它

   @override
  void initState() 
    // TODO: implement initState
    super.initState();
    new NotificationHandler().initializeFcmNotification();
  

【问题讨论】:

我面临同样的问题,有什么解决方案吗,我的 Flutter 应用程序支持 Kotlin,所以我的 mainactivity 类位于 Kotlin 文件夹中,我从该文件夹中的 firebase 文档中添加了应用程序类并转换它对 Kotlin 来说,有点不巧,它给出了同样的错误。 【参考方案1】:

编辑1:

浏览了几个git线程和***线程后,终于找到了一个无人能说的最短答案:

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

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


原文:

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

由于某种原因,设置

void initState() 
super.initState();
    _firebaseMessaging.configure

不工作,然后我尝试了

Future.delayed(Duration(seconds: 1), () 
     _firebaseMessaging.configure
    
);

我让它完美地工作:)

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

【讨论】:

GLOBAL SCOPE 是什么意思?能举个例子吗? @noamaghai 方法/函数外变量,全局作用域是高级编程基础知识,当您在方法/函数内部创建变量时,它仅在方法/函数内部可见,其生命周期只是生活在函数/方法调用的末尾 我熟悉 public function 术语,因为我来自 java c# 背景【参考方案2】:

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

onBackgroundMessage: myBackgroundMessageHandler

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

这是 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  ,
);

和处理程序模板:

Future<dynamic> myBackgroundMessageHandler(Map<String, dynamic> message) async  return Future<void>.value(); 

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

这是一个 PR,它提供了在 android 上处理后台通知的可能性。你可以找到详情here。

【讨论】:

现在我在后台正确接收通知,甚至应用程序也使用这种形式的代码关闭。但是当我关闭应用程序并在之后收到通知时,如果我点击否通知然后我的应用程序使用正确打开我的有效载荷的 onSelectNotification 方法。但在那之后,如果我将我的应用程序置于后台,那么我将无法再收到通知。你能帮我解决这个问题吗? 即使进行了上述修复,我仍然会看到此问题。您是否有更多关于如何解决此问题的详细信息? @Marche101 我有同样的问题,我的问题是方法需要是静态的!希望这会有所帮助。【参考方案3】:

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

我的 Firebase 消息传递实现

main.dart

initState()
  ....
  HelperClass.initFCM(some dependencies);

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,
      .....
      );
  

我无法在 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

当我像这样将函数设置为 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");
      

配置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.

【讨论】:

【参考方案4】:

提供的 onBackgroundMessageHandler 是一个***(不依赖于任何实例变量或字段)函数很重要。因此,有两种方法可以做到这一点:

1.)(最合适的)在任何类之外定义处理程序,以确保它是全局可用的并且不依赖于任何实例变量。

例子:

Future<void> onBackgroundNotificationData(RemoteMessage message) async 
  print(message.data);

  // do sommething...

2.) 将处理程序定义为类或接口中的静态方法。请注意,这是可行的,因为在 dart 中,静态方法无法访问实例变量方法或字段,因此它满足 onBackgroundMessage-handler 的结构要求。

例子:

class MyServiceClass 
  static Future<void> onBackgroundNotificationData(RemoteMessage message) async 
    print(message.data);

    // do sommething...
  

使用上述任何一种方法都应该有助于解决问题。

【讨论】:

以上是关于未处理的异常:NoSuchMethodError:在 null 上调用了方法“toRawHandle”的主要内容,如果未能解决你的问题,请参考以下文章

获取“未处理的异常:NoSuchMethodError:方法'map'在null上被调用”

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

Flutter,无法提取 api 数据:(未处理的异常:NoSuchMethodError:方法 'map' 在 null 上被调用。)

未处理的异常:NoSuchMethodError:在 null 上调用了方法“[]”(json 解析)

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

未处理的异常:NoSuchMethodError:在 null 上调用了方法“[]”。尝试调用:[](“is_ordered”)。检查空字段 Firebase [重复]