简体   繁体   English

Flutter:使用 FCM 在前台运行时,flutter_local_notifications 不起作用

[英]Flutter: flutter_local_notifications not work when running in Foreground with FCM

I want to implement FCM with flutter_local_notifications to handling notification from background and foreground .我想用flutter_local_notifications实现FCM来处理来自backgroundforeground的通知。 I already follow both documentation to setup the plugin.我已经按照这两个文档来设置插件。 And when I try on Android, the background notification is work and show the notification.当我尝试 Android 时, background通知正常工作并显示通知。 But when I try on foreground , the FCM is work (send the title and body ), but the notification not show ( get error ).但是当我在foreground尝试时, FCM工作(发送titlebody ),但通知不显示( get error )。 The detail error is bellow:详细错误如下:

D/FLTFireMsgReceiver(26448): broadcast received for message
W/roonapp.stagin(26448): Accessing hidden method Landroid/os/WorkSource;->add(I)Z (greylist, reflection, allowed)
W/roonapp.stagin(26448): Accessing hidden method Landroid/os/WorkSource;->add(ILjava/lang/String;)Z (greylist, reflection, allowed)
W/roonapp.stagin(26448): Accessing hidden method Landroid/os/WorkSource;->size()I (greylist, reflection, allowed)
W/roonapp.stagin(26448): Accessing hidden method Landroid/os/WorkSource;->get(I)I (greylist, reflection, allowed)
W/roonapp.stagin(26448): Accessing hidden method Landroid/os/WorkSource;->getName(I)Ljava/lang/String; (greylist, reflection, allowed)
[log] [32m——————————————————————————————————————————————————————————————————————
                DEBUG
——————————————————————————————————————————————————————————————————————
            2021-12-09T22:05:18.792141
——————————————————————————————————————————————————————————————————————
Show Notification:
Title -> test0
Body -> test0
Payload -> null

——————————————————————————————————————————————————————————————————————[0m
E/MethodChannel#dexterous.com/flutter/local_notifications(26448): Failed to handle method call
E/MethodChannel#dexterous.com/flutter/local_notifications(26448): java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Intent android.content.Intent.setAction(java.lang.String)' on a null object reference
E/MethodChannel#dexterous.com/flutter/local_notifications(26448):   at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.createNotification(FlutterLocalNotificationsPlugin.java:187)
E/MethodChannel#dexterous.com/flutter/local_notifications(26448):   at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.showNotification(FlutterLocalNotificationsPlugin.java:1023)
E/MethodChannel#dexterous.com/flutter/local_notifications(26448):   at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.show(FlutterLocalNotificationsPlugin.java:1358)
E/MethodChannel#dexterous.com/flutter/local_notifications(26448):   at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.onMethodCall(FlutterLocalNotificationsPlugin.java:1240)
E/MethodChannel#dexterous.com/flutter/local_notifications(26448):   at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:233)
E/MethodChannel#dexterous.com/flutter/local_notifications(26448):   at io.flutter.embedding.engine.dart.DartMessenger.handleMessageFromDart(DartMessenger.java:84)
E/MethodChannel#dexterous.com/flutter/local_notifications(26448):   at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:865)
E/MethodChannel#dexterous.com/flutter/local_notifications(26448):   at android.os.MessageQueue.nativePollOnce(Native Method)
E/MethodChannel#dexterous.com/flutter/local_notifications(26448):   at android.os.MessageQueue.next(MessageQueue.java:336)
E/MethodChannel#dexterous.com/flutter/local_notifications(26448):   at android.os.Looper.loop(Looper.java:197)
E/MethodChannel#dexterous.com/flutter/local_notifications(26448):   at android.app.ActivityThread.main(ActivityThread.java:7948)
E/MethodChannel#dexterous.com/flutter/local_notifications(26448):   at java.lang.reflect.Method.invoke(Native Method)
E/MethodChannel#dexterous.com/flutter/local_notifications(26448):   at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
E/MethodChannel#dexterous.com/flutter/local_notifications(26448):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1075)
E/flutter (26448): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: PlatformException(error, Attempt to invoke virtual method 'android.content.Intent android.content.Intent.setAction(java.lang.String)' on a null object reference, null, java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Intent android.content.Intent.setAction(java.lang.String)' on a null object reference
E/flutter (26448):  at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.createNotification(FlutterLocalNotificationsPlugin.java:187)
E/flutter (26448):  at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.showNotification(FlutterLocalNotificationsPlugin.java:1023)
E/flutter (26448):  at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.show(FlutterLocalNotificationsPlugin.java:1358)
E/flutter (26448):  at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.onMethodCall(FlutterLocalNotificationsPlugin.java:1240)
E/flutter (26448):  at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:233)
E/flutter (26448):  at io.flutter.embedding.engine.dart.DartMessenger.handleMessageFromDart(DartMessenger.java:84)
E/flutter (26448):  at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:865)
E/flutter (26448):  at android.os.MessageQueue.nativePollOnce(Native Method)
E/flutter (26448):  at android.os.MessageQueue.next(MessageQueue.java:336)
E/flutter (26448):  at android.os.Looper.loop(Looper.java:197)
E/flutter (26448):  at android.app.ActivityThread.main(ActivityThread.java:7948)
E/flutter (26448):  at java.lang.reflect.Method.invoke(Native Method)
E/flutter (26448):  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
E/flutter (26448):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1075)
E/flutter (26448): )
E/flutter (26448): #0      StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:607:7)
E/flutter (26448): #1      MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:156:18)
E/flutter (26448): <asynchronous suspension>
E/flutter (26448): #2      FlutterLocalNotificationsPlugin.show (package:flutter_local_notifications/src/flutter_local_notifications_plugin.dart:194:7)
E/flutter (26448): <asynchronous suspension>
E/flutter (26448): #3      NotificationHelper.showNormalNotification (package:notification/notification/notifications_helper.dart:85:5)
E/flutter (26448): <asynchronous suspension>
E/flutter (26448): 

Library Version库版本

firebase_core: ^1.10.0
firebase_messaging: ^11.2.3
firebase_analytics: ^9.0.2
flutter_local_notifications: ^9.1.4

AndroidManifest.xml AndroidManifest.xml


    <application
        ...>
        <activity
            android:showWhenLocked="true"
            android:turnScreenOn="true">
            ...
        </activity>
        
        ...
        
        <meta-data
            android:name="com.google.firebase.messaging.default_notification_channel_id"
            android:value="channel_id_app" />
    </application>

main.dart main.dart

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await Firebase.initializeApp();

  ...

  await NotificationConfig.init();

  runApp(App());
}

NotificationConfig通知配置

class NotificationConfig {
  static init() async {
    final notificationHelper = NotificationHelper();

    try {
      FirebaseMessaging.onBackgroundMessage(fcmBackgroundHandler); //This work fine
    } catch (e, trace) {
      Logger.e('Error Running Notification in Background: $e',
          ex: e, stacktrace: trace);
    }

    //TODO: Foreground not work (the notification)
    try {
      FirebaseMessaging.onMessage.listen((RemoteMessage message) {
        final notification = message.notification;
        if (notification != null) {
          final body = ReceivedNotification(
            title: notification.title,
            body: notification.body,
          );
          notificationHelper.showNormalNotification(body); //TODO: This is error when from `foreground`
        }
      });
    } catch (e, trace) {
      Logger.e('Error Running Notification in Foreground: $e',
          ex: e, stacktrace: trace);
    }
  }
}

NotificationHelper通知助手

Future<void> fcmBackgroundHandler(RemoteMessage message) async {
  final notificationHelper = NotificationHelper(); 

  final body = ReceivedNotification(
    title: message.notification?.title,
    body: message.notification?.body,
  );

  await notificationHelper.showNormalNotification(body); //TODO: This is not error when from `background`
}

class NotificationHelper {
  /// Singleton pattern
  static NotificationHelper? _instance;

  NotificationHelper._internal() {
    _instance = this;
    _init();
  }

  factory NotificationHelper() =>
      _instance ?? NotificationHelper._internal();

  final _flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();

  Future<void> _init() async {
    await _setupLocalNotification();
    await _setupFcm();
  }

Future<void> _setupLocalNotification() async {
    const channel = AndroidNotificationChannel(
      NotificationChannel.channelId,
      NotificationChannel.channelName,
      description: NotificationChannel.channelDesc,
      importance: Importance.max,
    );

    /// Initialization Settings for Android
    const initializationSettingsAndroid =
        AndroidInitializationSettings('@mipmap/ic_launcher');

    /// Initialization Settings for iOS
    const initializationSettingsIOS = IOSInitializationSettings(
      requestSoundPermission: false,
      requestBadgePermission: false,
      requestAlertPermission: false,
    );

    /// InitializationSettings for initializing settings for both platforms
    const initializationSettings = InitializationSettings(
      android: initializationSettingsAndroid,
      iOS: initializationSettingsIOS,
    );

    await _flutterLocalNotificationsPlugin.initialize(
      initializationSettings,
    );

    /// Create an Android Notification Channel.
    ///
    /// We use this channel in the `AndroidManifest.xml` file to override the
    /// default FCM channel to enable heads up notifications.
    await _flutterLocalNotificationsPlugin
        .resolvePlatformSpecificImplementation<
            AndroidFlutterLocalNotificationsPlugin>()
        ?.createNotificationChannel(channel);
  }

  Future<void> showNormalNotification(
    ReceivedNotification? notification,
  ) async {
    Logger.d(
      'Show Notification:\n'
      'Title -> ${notification?.title}\n'
      'Body -> ${notification?.body}\n'
      'Payload -> ${notification?.payload}\n',
    );

    await _flutterLocalNotificationsPlugin.show(
      NotificationType.normal,
      notification?.title,
      notification?.body,
      const NotificationDetails(
        android: AndroidNotificationDetails(
          NotificationChannel.channelId,
          NotificationChannel.channelName,
          channelDescription: NotificationChannel.channelDesc,
          priority: Priority.high,
          importance: Importance.max,
        ),
      ),
      payload: notification?.payload,
    );
  }

Future<void> _setupFcm() async {
    final fcm = FirebaseMessaging.instance;

    await fcm.setForegroundNotificationPresentationOptions(
      alert: true,
      badge: true,
      sound: true,
    );

    final token = await fcm.getToken();
    Logger.d("Token FCM: $token");

    ...
  }

}

As you can see above, both Foreground and Background call some function notificationHelper.showNormalNotification(body) .正如您在上面看到的, ForegroundBackground都调用了一些 function notificationHelper.showNormalNotification(body) But when it's from Foreground getting error like in the above logcat, and when from Background it's work.但是,当它来自Foreground时,会出现上述 logcat 中的错误,而当来自Background时,它就可以工作。

What I miss to setup flutter_local_notifications to work's when running in Foreground ?Foreground中运行时,我错过了将flutter_local_notifications设置为工作的内容吗?

Finally, after spend 2 days of work I found my solution.最后,经过两天的工作,我找到了解决方案。

The notification not show when app is open or running in foreground it's because in my AndroidManifest.xml have intent service for deeplink .当应用程序打开或在foreground运行时,通知不会显示,这是因为在我的AndroidManifest.xml中有用于deeplinkintent service

<intent-filter>
    ....

        <data android:scheme="${deeplink_schema}" />
</intent-filter>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM