在 Flutter 中,我们如何使用 Firebase Messaging onBackgroundMessage 创建通知,使用flutter_local_notifications?

Posted

技术标签:

【中文标题】在 Flutter 中,我们如何使用 Firebase Messaging onBackgroundMessage 创建通知,使用flutter_local_notifications?【英文标题】:In Flutter, how do we use Firebase Messaging onBackgroundMessage to create a notification, using flutter_local_notifications? 【发布时间】:2020-04-23 22:43:44 【问题描述】:

我们正在开发一个加密聊天应用程序,我们在其中使用 Firebase 消息传递数据通知。在向用户显示实际通知之前,需要在接收到数据通知时完成一些客户端逻辑。例如,必须将电话号码转换为本地联系人姓名。这种翻译是通过查找全球已经可用的地图来完成的。

数据通知被很好地接收,并且 onBackgroundMessage 回调也被调用。但是,似乎不可能从 onBackgroundMessage 函数访问任何类型的状态。例如,打印登录用户的电话号码返回 null。 从 onMessage 回调中打印相同的全局变量就可以了。

从 onMessage 运行 flutter_local_notifications 工作正常,但同样,从 onBackgroundMessage 根本不起作用,因为“找不到方法 .show() 的实现”。目前,它声称 flutterLocalNotificationsPlugin 为空,但实际上并非如此。

在我们看来,一旦应用程序处于后台,onBackgroundMessage 就无法访问应用程序提供的任何内容。必须做一些事情以使某些范围/上下文可用于后台进程。目前,这主要是flutter_local_notifications插件的整体,以及将电话号码转换为姓名的本地联系人列表。

有人知道怎么做吗?

以下是部分代码:

FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;
final _chatRepository = ChatRepository();

Future<dynamic> backgroundMessageHandler(Map<String, dynamic> message) async 
  if(message.containsKey('data')) 
    await _showNotification(message);
    return Future<void>.value();
  


Future _showNotification(message) async 
  List<String> numbers = [];
  numbers.add(message['data']['sender']);
  var name = await _chatRepository.translatePhoneNumbersToChatName(numbers);
  var androidPlatformChannelSpecifics = new AndroidNotificationDetails(
      'channel id', 'channel name', 'channel description',
      importance: Importance.Max, priority: Priority.High);
  var iosPlatformChannelSpecifics = new IOSNotificationDetails();
  var platformChannelSpecifics = new NotificationDetails(
      androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
  await flutterLocalNotificationsPlugin.show(
    0,
    name,
    message['data']['body'],
    platformChannelSpecifics,
    payload: message['data']['body'],
  );


class NotificationHandler 
  final FirebaseMessaging fcm = FirebaseMessaging();
  StreamSubscription iosSubscription;
  String deviceToken = "";

  Future<void> initialize() async 
    flutterLocalNotificationsPlugin = new FlutterLocalNotificationsPlugin();
    var initializationSettingsAndroid =
    new AndroidInitializationSettings('@mipmap/ic_launcher');
    var initializationSettingsIOS = new IOSInitializationSettings(onDidReceiveLocalNotification: onDidReceiveLocalNotification);
    var initializationSettings = new InitializationSettings(initializationSettingsAndroid, initializationSettingsIOS);
    flutterLocalNotificationsPlugin.initialize(initializationSettings, onSelectNotification: onClickNotification);

    fcm.configure(
      onMessage: (Map<String, dynamic> message) async 
        if(message.containsKey('data')) 
          print(message);
          _showNotification(message);
        
      ,
      onBackgroundMessage: Platform.isIOS
          ? null
          : backgroundMessageHandler,
      onLaunch: (Map<String, dynamic> message) async 
        if(message.containsKey('data')) 
          print(message);
          _showNotification(message);
        
      ,
      onResume: (Map<String, dynamic> message) async 
        if(message.containsKey('data')) 
          print(message);
          _showNotification(message);
        
      ,
    );
    _updateDeviceToken();
  
.
.
.

Of course, the initialize above is called early on in the application lifecycle.

【问题讨论】:

【参考方案1】:

这个插件比我解释得更好,但碰巧背景是完全不同的隔离/上下文,因此如果它们使用旧的(Flutter 12 之前的)API,它就无法访问任何插件。 https://pub.dev/packages/android_alarm_manager#flutter-android-embedding-v1

嵌入 v1 要求您注册要从后台访问的任何插件。这样做可以让 flutter_local_notifications 正常工作。

不幸的是,FCM 文档严重缺乏。

【讨论】:

【参考方案2】:
class NotificationHandler 
  static final flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); // make it a static field of the class
  // ...


Future _showNotification(message) async 
  // ...
  await NotificationHandler.flutterLocalNotificationsPlugin.show( // access it
    // ...
  );

希望这对你有用。

【讨论】:

您好,感谢您的回答。我尝试了两种方法,然后尝试了一些方法。接下来的错误是这样的:I/flutter (20856): Unable to handle incoming background message. I/flutter (20856): MissingPluginException(No implementation found for method show on channel dexterous.com/flutter/local_notifications) 所以它可以找到 FlutterLocalNotificationPlugin 的实例,但它似乎找不到它的实现方法。 @b0nes 您是否完成了处理后台消息所需的步骤? (pub.dev/packages/…) @b0nes 您可能忘记了做某事。我建议您检查您是否正确完成了flutter_local_notificationsfirebase_messaging 的安装。另外,试试flutter cleanflutter pub get @b0nes ***.com/a/59836752/5546443 你试过这个吗?

以上是关于在 Flutter 中,我们如何使用 Firebase Messaging onBackgroundMessage 创建通知,使用flutter_local_notifications?的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 现有项目到 WebApp + Firebase (Firestore + Hosting)

未收到 Flutter FCM IOS 静默(仅数据)通知

Flutter web Firebase 分析类型错误:dart.global.firebase.analytics 不是函数

Firebase for Flutter 登录构建失败

构建 Flutter iOS 应用程序时出错 - Firebase

在 Flutter 中,我们如何使用 Firebase Messaging onBackgroundMessage 创建通知,使用flutter_local_notifications?