我正在设置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.access$1800(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));
});
....