java.lang.RuntimeException: 接收到 firebase 消息时无法创建服务错误

java.lang.RuntimeException: Unable to create service error when receiving a firebase messaging message

我正在设置 FirebaseMessaging,当我收到消息时,我确实得到了我在 .onMessage 回调中设置的打印件:

I/flutter (27328): New FCM onMessage message : Instance of 'RemoteMessage' 
I/flutter (27328): 
I/flutter (27328): New FCM onMessage message id: 0:1653641357492638%dad60691dad60691
W/com.xxx.foods(27328): Accessing hidden method Landroid/os/WorkSource;->add(I)Z (unsupported,test-api, reflection, allowed)
I/flutter (27328): New FCM onMessage message sentTime: 2022-05-27 10:49:17.485
W/com.xxx.foods(27328): Accessing hidden method Landroid/os/WorkSource;->add(ILjava/lang/String;)Z (unsupported,test-api, reflection, allowed)
W/com.xxx.foods(27328): Accessing hidden method Landroid/os/WorkSource;->get(I)I (unsupported, reflection, allowed)
W/com.xxx.foods(27328): Accessing hidden method Landroid/os/WorkSource;->getName(I)Ljava/lang/String; (unsupported, reflection, allowed)
I/flutter (27328): New FCM onMessage message notification title: a
I/flutter (27328): New FCM onMessage message notification body: a

但随后应用程序崩溃并出现错误:

D/AndroidRuntime(27328): Shutting down VM E/AndroidRuntime(27328): FATAL EXCEPTION: main E/AndroidRuntime(27328): Process: com.xxx.foods, PID: 27328 E/AndroidRuntime(27328): java.lang.RuntimeException: Unable to create service com.example.xxx.java.MyFirebaseMessagingService: java.lang.ClassNotFoundException: Didn't find class "com.example.xxx.java.MyFirebaseMessagingService" on path: DexPathList[[zip file "/data/app/~~LYrL5kv915DhEfzUSgPwZg==/com.xxx.foods-dIN5_0rsX6Wo-G0jfKtL2Q==/base.apk"],nativeLibraryDirectories=[/data/app/~~LYrL5kv915DhEfzUSgPwZg==/com.xxx.foods-dIN5_0rsX6Wo-G0jfKtL2Q==/lib/arm64, /data/app/~~LYrL5kv915DhEfzUSgPwZg==/com.xxx.foods-dIN5_0rsX6Wo-G0jfKtL2Q==/base.apk!/lib/arm64-v8a, /system/lib64, /system_ext/lib64]] E/AndroidRuntime(27328):  at android.app.ActivityThread.handleCreateService(ActivityThread.java:4619) E/AndroidRuntime(27328):    at android.app.ActivityThread.access00(ActivityThread.java:265) E/AndroidRuntime(27328):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2122) E/AndroidRuntime(27328):    at android.os.Handler.dispatchMessage(Handler.java:106) E/AndroidRuntime(27328):    at android.os.Looper.loopOnce(Looper.java:210) E/AndroidRuntime(27328):     at android.os.Looper.loop(Looper.java:299) E/AndroidRuntime(27328):     at android.app.ActivityThread.main(ActivityThread.java:8166) E/AndroidRuntime(27328):   at java.lang.reflect.Method.invoke(Native Method) E/AndroidRuntime(27328):  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:556) E/AndroidRuntime(27328):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1037) E/AndroidRuntime(27328): Caused by: java.lang.ClassNotFoundException: Didn't find class "com.example.xxx.java.MyFirebaseMessagingService" on path: DexPathList[[zip file "/data/app/~~LYrL5kv915DhEfzUSgPwZg==/com.xxx.foods-dIN5_0rsX6Wo-G0jfKtL2Q==/base.apk"],nativeLibraryDirectories=[/data/app/~~LYrL5kv915DhEfzUSgPwZg==/com.xxx.foods-dIN5_0rsX6Wo-G0jfKtL2Q==/lib/arm64, /data/app/~~LYrL5kv915DhEfzUSgPwZg==/com.xxx.foods-dIN5_0rsX6Wo-G0jfKtL2Q==/base.apk!/lib/arm64-v8a, /system/lib64, /system_ext/lib64]] E/AndroidRuntime(27328):     at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:218) E/AndroidRuntime(27328):     at java.lang.ClassLoader.loadClass(ClassLoader.java:379) E/AndroidRuntime(27328):   at java.lang.ClassLoader.loadClass(ClassLoader.java:312) E/AndroidRuntime(27328):   at android.app.AppComponentFactory.instantiateService(AppComponentFactory.java:129) E/AndroidRuntime(27328):    at androidx.core.app.CoreComponentFactory.instantiateService(CoreComponentFactory.java:75) E/AndroidRuntime(27328):     at android.app.ActivityThread.handleCreateService(ActivityThread.java:4588) E/AndroidRuntime(27328):    ... 9 more D/OOMEventManagerFK(27328): checkEventAndDumpForJE: 0 I/Process (27328): Sending signal. PID: 27328 SIG: 9 Lost connection to device

在我的 android/app/main/AndroidManifest.xml 中,我设置了文档中描述的服务:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.xxx">
    <!-- io.flutter.app.FlutterApplication is an android.app.Application that
         calls FlutterMain.startInitialization(this); in its onCreate method.
         In most cases you can leave this as-is, but you if you want to provide
         additional functionality it is fine to subclass or reimplement
         FlutterApplication and put your custom class here. -->

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <application
        android:name="io.flutter.app.FlutterApplication"
        android:label="xxx"
        android:icon="@mipmap/ic_launcher">

        <activity
            android:name=".MainActivity"
            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"
              />
            <!-- Displays an Android View that continues showing the launch screen
                 Drawable until Flutter paints its first frame, then this tutorial
                 screen fades out. A tutorial screen is useful to avoid any visual
                 gap between the end of Android's launch screen and the painting of
                 Flutter's first frame. -->
            <meta-data
              android:name="io.flutter.embedding.android.SplashScreenDrawable"
              android:resource="@drawable/launch_background"
              />
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <service
            android:name=".java.MyFirebaseMessagingService"
            android:exported="false">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
            </intent-filter>
        </service>

        <!-- 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" />
    </application>
</manifest>

并在 MainActivity.kt 中我设置了 FlutterFragmentedActivity:

package com.example.xxx

//import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.android.FlutterFragmentActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.GeneratedPluginRegistrant
import androidx.annotation.NonNull;

//class MainActivity: FlutterActivity() {
//}
class MainActivity: FlutterFragmentActivity() {
    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        GeneratedPluginRegistrant.registerWith(flutterEngine);
    }
}

还有什么我应该设置的吗?

我是这样初始化的:

  print('New FCM firebaseMessagingBackgroundHandler message : ${message.toString()} \n\n');
  print('New FCM firebaseMessagingBackgroundHandler message id: ${message.messageId}');
  print('New FCM firebaseMessagingBackgroundHandler message sentTime: ${message.sentTime}');

  print('New FCM firebaseMessagingBackgroundHandler message notification title: ${message.notification.title}');
  print('New FCM firebaseMessagingBackgroundHandler message notification body: ${message.notification.body}');
  await Firebase.initializeApp();
}

void main() async {
  // set the publishable key for Stripe - this is mandatory
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  FirebaseMessaging.onBackgroundMessage(firebaseMessagingBackgroundHandler);

...


但是,由于我需要在收到消息时发送 Bloc 事件,我在下一个屏幕中设置了 FirebaseMessaging,这将使 Bloc 在树中可用:

class _ShowSplashScreenWidgetState extends State<ShowSplashScreenWidget> {
  final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance;
  String fcmToken;

  @override
  void initState() {
    super.initState();

    /// FCM setup

    _firebaseMessaging.requestPermission(sound: true, badge: true, alert: true, provisional: false, carPlay: false, criticalAlert: false);

    _firebaseMessaging.getToken().then((token) {
      print(' _firebaseMessaging.getToken token: $token');

      if (mounted) {
        setState(() {
          fcmToken = token;
        });
      } else {
        fcmToken = token;
      }
    });

    FirebaseMessaging.onMessage.listen((message) {
      print('New FCM onMessage message : ${message.toString()} \n\n');
      print('New FCM onMessage message id: ${message.messageId}');
      print('New FCM onMessage message sentTime: ${message.sentTime}');

      print('New FCM onMessage message notification title: ${message.notification.title}');
      print('New FCM onMessage message notification body: ${message.notification.body}');

      NotificationModel notification = NotificationModel(
          id: message.messageId, read: false, date: message.sentTime, title: message.notification.title, body: message.notification.body);
      // BlocProvider.of<NotificationBloc>(context).add(SaveNotification(notification: notification));
    });

    FirebaseMessaging.onMessageOpenedApp.listen((message) {
      print('New FCM onMessageOpenedApp message : ${message.toString()} \n\n');
      print('New FCM onMessageOpenedApp message id: ${message.messageId}');
      print('New FCM onMessageOpenedApp message sentTime: ${message.sentTime}');

      print('New FCM onMessageOpenedApp message notification title: ${message.notification.title}');
      print('New FCM onMessageOpenedApp message notification body: ${message.notification.body}');
      NotificationModel notification = NotificationModel(
          id: message.messageId, read: false, date: message.sentTime, title: message.notification.title, body: message.notification.body);
      BlocProvider.of<NotificationBloc>(context).add(SaveNotification(notification: notification));
    });

....


你有 class java.MyFirebaseMessagingService 吗? 另外,在较新版本的 FCM 中,您不必在清单或代码中初始化服务 class, 很简单,从 AndroidManifest.xml

中删除 MyFirebaseMessagingService 服务标签