I'm setting up FirebaseMessaging
and when I receive the message I do get the prints I setup in the .onMessage
callback:
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
but then the app crashes with the error:
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
In my android/app/main/AndroidManifest.xml I setup a service as described in the docs:
<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>
and in MainActivity.kt
I setup 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);
}
}
Is there something else I should setup?
I initialise it like so:
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);
...
but then, as I need to send a Bloc event when receiving a message, I set FirebaseMessaging in the next screen which would have the Bloc available in the tree:
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));
});
....
Do you have the class java.MyFirebaseMessagingService
?
plus, in newer versions of FCM, you don't have to initialize a service class neither in your Manifest or your code,
simple, remove MyFirebaseMessagingService
service tag from your AndroidManifest.xml
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With