firebase_messaging onResume 和 onLaunch 不起作用

Posted

技术标签:

【中文标题】firebase_messaging onResume 和 onLaunch 不起作用【英文标题】:firebase_messaging onResume and onLaunch not working 【发布时间】:2019-09-25 06:25:44 【问题描述】:

当应用程序在前台时我会收到通知,但当应用程序在后台时不会。此外,我已经 google-ed/***-ed 了大约 2 小时或更长时间,但能够解决这个问题。

我的配置是:

  firebase_auth: ^0.10.0
  firebase_messaging: ^5.0.0

清单是这样的:

代码是这样的:

final notifications = new FirebaseMessaging();

class AppNotifications 
  static String fcmToken = '';

  static Future<Null> init() async 
    appLogs("AppNotifications init");

    notifications.requestNotificationPermissions(const iosNotificationSettings(sound: true, badge: true, alert: true));

    await configure();

    fcmToken = await notifications.getToken();
    appLogs("FCM TOKEN : " + fcmToken);

    notifications.onTokenRefresh.listen((newToken) 
      fcmToken = newToken;
      appLogs("FCM TOKEN onTokenRefresh: " + fcmToken);
    );

    await updateFCMToken();
  

  static Future<Null> configure() async 
    appLogs("AppNotifications Configure");

    notifications.configure(onMessage: (msg) 
      appLogs('FCM onMessage: ' + msg.toString());
    , onLaunch: (lun) 
      appLogs('FCM onLaunch: ' + lun.toString());
    , onResume: (res) 
      appLogs('FCM onResume: ' + res.toString());
    );
  

  static Future<Null> updateFCMToken() async 
    auth.currentUser.fcmToken = fcmToken;
    await updateUserInSharedPreference();
  

我这样调用函数:

class HomeScreenState extends State<HomeScreen> 


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

    Future.delayed(Duration(milliseconds: 100), () async 
      await AppNotifications.init();
    );
  

..... ....

我正在使用邮递员发送通知:

我的日志:

**(App is Foreground)**  I/flutter (31888): APPLOGS : FCM onMessage: notification: title: Test notification title, body: Test notification body, data: status: done, id: 1, foo: bar, click_action: FLUTTER_NOTIFICATION_CLICK
  **(App is Background)**  W/FirebaseMessaging(31888): Missing Default Notification Channel metadata in androidManifest. Default value will be used.

颤振医生:

[✓] Flutter (Channel stable, v1.2.1, on Mac OS X 10.14.4 18E226, locale en-GB)
    • Flutter version 1.2.1 at /Users/Ajay/SDK/flutter
    • Framework revision 8661d8aecd (3 months ago), 2019-02-14 19:19:53 -0800
    • Engine revision 3757390fa4
    • Dart version 2.1.2 (build 2.1.2-dev.0.0 0a7dcf17eb)

[✓] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
    • Android SDK at /Users/Ajay/Library/Android/sdk
    • Android NDK location not configured (optional; useful for native profiling support)
    • Platform android-28, build-tools 28.0.3
    • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1248-b01)
    • All Android licenses accepted.

[✓] iOS toolchain - develop for iOS devices (Xcode 10.2.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 10.2.1, Build version 10E1001
    • ios-deploy 1.9.4
    • CocoaPods version 1.6.0

[✓] Android Studio (version 3.3)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin version 34.0.1
    • Dart plugin version 182.5215
    • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1248-b01)

[!] VS Code (version 1.33.1)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    ✗ Flutter extension not installed; install from
      https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter

[✓] Connected device (1 available)
    • ONEPLUS A5000 • b47e8396 • android-arm64 • Android 9 (API 28)

【问题讨论】:

我也在为 Android 上的通知支持而苦苦挣扎。除了应用程序在前台时我没有收到通知。但即使有“后台到达”通知,数据有效负载也会在应用启动时丢失。 iOS 运行得非常好。 我终于通过在 runApp(MyApp()) 中初始化 Firebase 解决了我的 Firebase 消息传递问题。由于您似乎已经这样做了,您的代码流和我的代码流之间的唯一区别是您使用版本5.0.0。你试过降级吗?例如。我用4.0.0+4 @George 当从 API.onLaunch 收到推送通知时,必须单击操作参数,并且未调用 onResume。 @AjayKumar 你解决了这个问题吗? 如果您针对 Android 设备,建议使用 @ShangariC click_action。否则,当用户单击托盘中的通知时,不会调用 onLaunch / onResume。有关详细信息,请查看文档中的 Sending Messages 【参考方案1】:

我花了 2 天时间来解决这个问题,它可能对你有帮助。 notification 标记仅用于显示通知。您只能访问 onResume/onLaunch 上的数据内容。

如果你想在 onResume/onLaunch 中处理通知消息,也可以在 data 标签中添加这些消息,然后你可以做任何你想做的事情。

refer more detail on this link

发送此通知消息


       "notification": 
          "body": "body",
          "title": "title"
       ,
       "priority": "high",
       "data": 
        "body": "body",
          "title": "title"
          "click_action": "FLUTTER_NOTIFICATION_CLICK",
          "id": "1",
          "status": "done",
          "image": "https://ibin.co/2t1lLdpfS06F.png",
       ,
       "to": <your token>
    

您将收到以下关于Resume 或onLaunch 的信息,您的通知标签在此处为空

notification: , data: image: https://ibin.co/2t1lLdpfS06F.png, google.original_priority: high, google.sent_time: 1560858283888, google.delivered_priority: high, body: body , title: title, click_action: FLUTTER_NOTIFICATION_CLICK, google.message_id: 0:1560858283908500%eefdc741eefdc741, collapse_key: <package>, google.ttl: 2419200, from: <from>, id: 1, status: done

您可以使用添加在数据标签中的标题和正文。

【讨论】:

这是正确答案! click_action 键需要在 data 对象内。 Firebase 没有记录在案。 当 click_action 是 n 通知而不是数据时它正在工作? 完全同意 Anand Saga , 在一些教程中,他们提到了会导致此问题的“clickAction” @MDavid 你能告诉我我在哪条路线上放了firebase init的代码吗?我已经添加了这个,但仍然没有工作。通知在后台显示,但 onResume 不起作用..【参考方案2】:

就我而言,onResumeonLoad 没有触发,因为我在 notification 属性下缺少 click_action: 'FLUTTER_NOTIFICATION_CLICK'不是data 属性。

一旦我将有效载荷更改为以下格式,onResumeonLoad 就开始为我触发。


    notification: 
        title: 'Title',
        body: 'Body',
        click_action: 'FLUTTER_NOTIFICATION_CLICK'
    

我发现这个记录在here。

如果您在 TypeScript(可能是其他人)中设置它,则需要通过消息的 android.notification.clickAction 属性进行设置。否则,您可能会收到有关属性无效的错误。 MulticastMessage 的示例如下。请注意,它不会从头到尾显示消息构造;仅足以显示设置clickAction 的上下文。

// Initialize the notification
const notification: admin.messaging.Notification = 
    title: 'Hello',
    // Though the "clickAction" property is available here, it throws an error about
    // having an invalid property when actually trying to send the notification.
    // Instead, the "clickAction" property is set further downstream under the
    // MulticastMessage.android.notification object.
    // clickAction: 'FLUTTER_NOTIFICATION_CLICK'
;

// Do other things to build your notification

const message: admin.messaging.MulticastMessage = 
    tokens: [],
    notification: notification
;

// Do other things to build your message

// If a notification is being sent then set the click_action
if (message.notification) 
    // Combine with the existing message.android object, if one exists
    message.android = message.android || ;
    message.android.notification = Object.assign(message.android.notification || , 
        clickAction: 'FLUTTER_NOTIFICATION_CLICK'
    );

【讨论】:

如果放置在数据标签内,它会启动我的活动。但 onResume 和 onLoad 不起作用。 如果我将它添加到 notification 有效负载中,我会收到此错误:Invalid JSON payload received. Unknown name "click_action" at \'message.notification\': Cannot find field. 我更新了我的答案,以展示我们如何在代码中设置它的示例。【参考方案3】:

在本节 link to plugin docs 中的 firebase_messaging 包的文档中,他们说您需要将 click_action: FLUTTER_NOTIFICATION_CLICK 作为“自定义数据”键值对包含在您的 onResume 和 @ 的服务器端发布请求中987654325@要调用的方法。

例如,这里使用the php firebase admin sdk 向 FCM 发送通知,这是发送通知的代码示例:

        $factory = (new Factory)->withServiceAccount('path to firebase keys json file');
                $messaging = $factory->createMessaging();

                $deviceToken = $user->deviceToken;
    $message = CloudMessage::withTarget('token', $deviceToken)
                        ->withNotification(Messaging\Notification::create('title', 'body'))
                        ->withData(['custom-data-key1' => 'custom-data-value1', 'custom-data-key2' => 'custom-data-value2', 'click_action'=>'FLUTTER_NOTIFICATION_CLICK']);
$messaging->send($message);

【讨论】:

【参考方案4】:

您可能在 AndroidManifest 中缺少一些元数据(正如您的日志告诉您的那样)。 您需要在清单中添加以下内容:

<meta-data
    android:name="com.google.firebase.messaging.default_notification_channel_id"
    android:value="@string/default_notification_channel_id"/>

好像是duplicate

【讨论】:

【参考方案5】:

Anand saga 发布的答案是正确的

您需要在数据部分添加标题和正文。通知负载将是空白 onResume 和 onLaunch 虽然它是从后端 nodejs API 发送的。

以下是 Flutter 解析为 onResume 的示例负载:

on resume notification: , data: image: https://ibin.co/2t1lLdpfS06F.png, google.original_priority: normal, google.sent_time: 1577389234347, google.delivered_priority: normal, body: "Custom Body", type: OrderDetail, title: "Custom title", click_action: FLUTTER_NOTIFICATION_CLICK, google.message_id: 0:1577389234352165%dfef845edfef845e, collapse_key: <<App NAme>>, google.ttl: 2419200, from: 790713779055, id: "5e050c04c308f6abb5a60b2e"

典型的 dart 配置如下所示。

firebaseMessaging.configure(
      onMessage: (Map<String, dynamic> message) async 
        print('on message $json.encode(message['data']['title'])');
        redirectScreenOnLoad(message);
      ,

      onResume: (Map<String, dynamic> message) async 
        firebaseMessaging.onTokenRefresh;
        print('on resume $message');
        redirectScreenOnLoad(message);

      ,

      onLaunch: (Map<String, dynamic> message) async 
        firebaseMessaging.onTokenRefresh;
//        await API.updateUserApiToGetFCMKey();
        print('on launch $message');
        redirectScreenOnLoad(message);
      ,
    );

在 redirectScreenOnLoad(String message) 中,我正在检查输入负载并重定向到不同的屏幕

【讨论】:

这是在 Android 上,但在 iOS 中 [data] 在 json 中不存在,你是否也为 iOS 解决了这个问题我上周一直在使用这个在 onResume 上工作但在 onLaunch 上失败 我没有在 iOS 中测试过这个。你能发布你在 iOS 中从 firebase 消息中得到的响应吗? 让它工作我需要从 initiState 调用才能工作 redirectScreenOnLoad() 函数在哪里? 这是一个配置问题,您需要完全执行文档中的步骤,它会起作用【参考方案6】:

要为 FCM 故障排除添加的另一件事是在您的 onMessage 处理中。

首先,在onMessage 中,打印输出以查看您的设备是否正在接收消息。通知可能会在这一点之后失败并且不会显示,所以很高兴知道它是否得到它。如果是,那么您知道您已正确配置 FCM,并且您的问题在于您的 UI 处理。

接下来,检查onMessage 打印语句并确保您对数据的处理正确无误。我注意到 Android 数据的结构模式与 iOS 类型不同——因此这可能会导致您错误地解析数据,这可能不会显示通知,也不会引发错误。

这是我的意思的一个例子:

    _fcm.configure(
      onMessage: (Map<String, dynamic> message) async 
        print("onMessage: $message");
        String sender;
        String parsedMessage;

        if (Platform.isAndroid) 
          sender = message['notification']['title'];
          parsedMessage = message['notification']['body'];
        
        if (Platform.isIOS) 
          sender = message['aps']['alert']['title'];
          parsedMessage = message['aps']['alert']['body'];
        
      ,
    );

您可以看到,我根据平台不同地解析相同的数据。如果不这样做,则通知永远不会出现,也不会指示失败。

同样,这只是在您拆开 .ts/.js 云函数之前尝试的操作。

【讨论】:

【参考方案7】:

如果您的 android 应用程序在 kotlin 中,您应该将其添加为您的应用程序活动

import io.flutter.app.FlutterApplication
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback
import io.flutter.plugins.GeneratedPluginRegistrant
import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService

class Application : FlutterApplication(), PluginRegistrantCallback 

    override fun onCreate() 
        super.onCreate()
        FlutterFirebaseMessagingService.setPluginRegistrant(this);
    

    override fun registerWith(registry: PluginRegistry?) 
        io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin.registerWith(registry?.registrarFor("io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin"));
    

别忘了将它添加到您的 Manifist android:name=".Application"

【讨论】:

【参考方案8】:
onLaunch: (Map<String, dynamic> msg) 
    print("Called onLaunch");
    print(msg);
    if(msg['data']['screen'].toString() == 'chat') 
        //Navigate to chat screen
    
    return null;
,

【讨论】:

【参考方案9】:

处理 firebase 消息的完整指南:

handleMessaging() 
  _firebaseMessaging.configure(
    onMessage: (Map<String, dynamic> message) async 
      // showNotification(
      //     message['notification']['title'], message['notification']['body']);
      print("onMessage: $message");

      print('Data is: '+ message['data']['screen'].toString());

    ,
    onLaunch: (Map<String, dynamic> msg) 
      print("Called onLaunch");
      print(msg);
      print('Data is: '+ msg['data']['screen'].toString());

      if(msg['data']['screen'].toString() == 'Chat Screen') 
        return //Navigate to chatApp();
      
      return null;
    ,
    onResume: (Map<String, dynamic> msg) 
      //(App in background)
      // From Notification bar when user click notification we get this event.
      // on this event navigate to a particular page.
      print(msg);

      // // Assuming you will create classes to handle JSON data. :)
      // Notification ns = Notification(title: msg['title'], body: msg['body']);
      //        
      return null;
    ,
    // onMessage: (Map<String, dynamic> msg) 
    // // (App in foreground)
    // // on this event add new message in notification collection and hightlight the count on bell icon.
    // // Add notificaion add in local storage and show in a list.
  );

【讨论】:

【参考方案10】:

请注意,新版本的 FirebaseMessaging 是一个很大的变化,因此如果您发现此线程,以上所有内容都将不起作用。

Configure 消失了,与其他 Flutter 2 更新一样,都是通过 .listen 方法进行的。 有一个线程: How to configure Firebase Messaging with latest version in Flutter?

【讨论】:

以上是关于firebase_messaging onResume 和 onLaunch 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

firebase_messaging 如何清除通知?

firebase_messaging:^4.0.0+4 不工作

使用颤振 firebase_messaging 插件发送通知声音

firebase_messaging/unknown:Flutter IOS 出现未知错误

使用 firebase_messaging 自定义通知(Android 和 IOS)

无法使用 firebase_messaging 在 iOS 上的 Flutter 应用中订阅主题