首页 > 解决方案 > 颤振 - 用户打开推送通知消息(FCM)后如何执行任务

问题描述

我已经firebase cloud messaging (FCM)并且可以向我的用户发送消息。

但是,我想制作一个场景,如果我的用户在他们的手机上点击通知消息,那么应用程序将打开一个视图或弹出并执行一些后台任务。

这可能吗?

谢谢你

===根据 Shady Boshra 的建议更新问题

1)我创建谷歌云功能的火力基地使用typeScript

import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
admin.initializeApp();
const fcm = admin.messaging();

export const sendNotif = functions.https.onRequest((request, response) => {

   const tokens = request.query.tokens;
   const payload: admin.messaging.MessagingPayload = {
   notification: {
      title: '[TEST-123] title...',
      body: `[TEST-123]  body of message... `,          
      click_action: 'FLUTTER_NOTIFICATION_CLICK',
      tag: "news",
      data: "{ picture: 'https://i.imgur.com/bY2bBGN.jpg', link: 'https://example.com' }"
    }
  };
  const res = fcm.sendToDevice(tokens, payload);
  response.send(res);
});

2) 我更新了我的移动应用代码 / Dart

_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) {
  print("::==>onMessage: $message");

  message.forEach((k,v) => print("${k} - ${v}"));

  String link = "https://example.com";

  FlutterWebBrowser.openWebPage(url: link, androidToolbarColor: Pigment.fromString(UIData.primaryColor));
  return null;
},

然后我尝试在应用程序处于打开模式时发送推送通知。

但是,当我尝试调试它时,我找不到 data 的内容。它返回以下响应:

I/flutter (30602): ::==>onMessage: {notification: {body: [TEST-123] body of message... , title: [TEST-123] title...}, data: {}}

I/flutter (30602): ::==>onMessage: {notification: {body: [TEST-123] body of message... , title: [TEST-123] title...}, data: {}}

I/flutter (30602): 通知 - {body: [TEST-123] body of message... , title: [TEST-123] title...}

I/颤振 (30602):数据 - {}

I/flutter (30602): 通知 - {body: [TEST-123] body of message... , title: [TEST-123] title...}

I/颤振 (30602):数据 - {}

如您所见, 的内容data是空白的。

===更新2

如果我data通过删除双引号进行编辑,则会在运行时返回错误firebase deploy

> functions@ build /Users/annixercode/myPrj/backend/firebase/functions
> tsc

src/index.ts:10:4 - error TS2322: Type '{ title: string; body: string; click_action: string; tag: string; data: { picture: string; link: string; }; }' is not assignable to type 'NotificationMessagePayload'.
  Property 'data' is incompatible with index signature.
    Type '{ picture: string; link: string; }' is not assignable to type 'string'.

10    notification: {
      ~~~~~~~~~~~~

  node_modules/firebase-admin/lib/index.d.ts:4246:5
    4246     notification?: admin.messaging.NotificationMessagePayload;
             ~~~~~~~~~~~~
    The expected type comes from property 'notification' which is declared here on type 'MessagingPayload'


Found 1 error.

npm ERR! code ELIFECYCLE
npm ERR! errno 2
npm ERR! functions@ build: `tsc`
npm ERR! Exit status 2
npm ERR! 
npm ERR! Failed at the functions@ build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/anunixercode/.npm/_logs/2019-08-28T01_02_37_628Z-debug.log

Error: functions predeploy error: Command terminated with non-zero exit code2

==更新3(回应Shady Boshra的回答)

以下是我关于颤振的代码:

  _firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) {
  print("::==>onMessage: $message");

  message.forEach((k,v) => print("${k} - ${v}"));

  var data = message['notification']['data']['link'];
  print ("===>data_notif = "+data.toString());

  var data2 = message['data']['link'];
  print ("===>data_notif2 = "+data2.toString());
...

在我发送推送通知后,我刚刚在调试中收到以下消息:

The application is paused.
Reloaded 22 of 1277 libraries.
I/flutter (18608): 0
I/flutter (18608): AsyncSnapshot<String>(ConnectionState.active, Tuesday, September 3, 2019, null)
I/flutter (18608): ::==>onMessage: {notification: {body: [TEST-123]  body of message... , title: [TEST-123] title...}, data: {}}
I/flutter (18608): notification - {body: [TEST-123]  body of message... , title: [TEST-123] title...}
I/flutter (18608): data - {}
Application finished.

如您所见,我无法获得linkinside的价值data

标签: androidfirebaseflutterdartgoogle-cloud-functions

解决方案


当然,你也可以在 Flutter 上做到这一点。

首先,我希望您在清单中设置这些代码

<intent-filter> <action android:name="FLUTTER_NOTIFICATION_CLICK" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter>

在后端 (node.js) 中的 JSON 通知正文中添加标记元素。

const payload: admin.messaging.MessagingPayload = {
  notification: {
    title: 'New Puppy!',
    body: `${puppy.name} is ready for adoption`,
    icon: 'your-icon-url',
    tag: 'puppy', 
    data: {"click_action": "FLUTTER_NOTIFICATION_CLICK", "id": "1", "status": "done"}, 
    click_action: 'FLUTTER_NOTIFICATION_CLICK' // required only for onResume or onLaunch callbacks
  }
};

在 Dart 代码中,请确保在第一个 initState() 页面中设置此代码。

_fcm.configure(
      onMessage: (Map<String, dynamic> message) async {
        print("onMessage: $message");
        var tag = message['notification']['title']);

        if (tag == 'puppy') 
        {
         // go to puppy page
        } else if (tag == 'catty') 
        {
         // go to catty page
        } 
    },
    onLaunch: (Map<String, dynamic> message) async {
        print("onLaunch: $message");
        // TODO optional
    },
    onResume: (Map<String, dynamic> message) async {
        print("onResume: $message");
        // TODO optional
    },
  );

我的大部分答案来自这个博客

当回调触发时,它在博客中提到,因此请仔细决定将代码设置在哪一个中。

onMessage在应用程序打开并在前台运行时触发。

如果应用程序关闭但仍在后台运行,则onResume会触发。

如果应用程序完全终止,onLaunch会触发。

更新

由于您的问题已更新,请考虑本文中的以下内容

• 通知消息- 由标题和消息正文组成,并在到达设备时触发通知系统。换句话说,状态栏中会出现一个图标,通知栏会出现一个条目。在发送您希望用户看到的信息性消息时,应使用此类通知。

前任:

var payload = {
  notification: {
    title: "Account Deposit",
    body: "A deposit to your savings account has just cleared."
  }
};

• 数据消息- 包含键/值对形式的数据,并直接传送到应用程序而不触发通知系统。以静默方式向应用程序发送数据时使用数据消息。

前任:

var payload = {
  data: {
    account: "Savings",
    balance: "$3020.25"
  }
};

• 组合消息– 包含包含通知和数据的有效负载。通知显示给用户,数据传送到应用程序。

前任:

var payload = {
  notification: {
    title: "Account Deposit",
    body: "A deposit to your savings account has just cleared."
  },
  data: {
    account: "Savings",
    balance: "$3020.25"
  }
};

所以,我想你会使用第三个,它同时发送通知和数据。

您可以使用 dart 访问数据,如下所示。

message['data']['account']

更新 2

当您更新您的问题时,我的解决方案并没有很好地与您合作。我决定自己测试一下,你猜怎么着!它适用于您和相同的代码。

我的 node.js 后端代码

'use strict';

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

const db = admin.firestore();
const fcm = admin.messaging();

exports.sendNotification = functions.firestore
    .document('orders/{orderId}')
    .onCreate(async snapshot => {

        const order = snapshot.data();

        // Token of my device only
        const tokens = ["f5zebdRcsgg:APA91bGolg9-FiLlCd7I0LntNo1_7b3CS5EAJBINZqIpaz0LVZtLeGCvoYvfjQDhW0Qdt99jHHS5r5mXL5Up0kBt2M7rDmXQEqVl_gIpSQphbaL2NhULVv3ZkPXAY-oxX5ooJZ40TQ2-"];

        const payload = {
            notification: {
                title: "Account Deposit",
                body: "A deposit to your savings account has just cleared."
            },
            data: {
                account: "Savings",
                balance: "$3020.25",
                link: "https://somelink.com"
            }
        };

        return fcm.sendToDevice(tokens, payload);
    });

和飞镖代码

final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();

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

    _firebaseMessaging.requestNotificationPermissions();

    _firebaseMessaging.configure(
      onMessage: (Map<String, dynamic> message) async {
        print("onMessage: $message");

        var data2 = message['data']['link'];
        print ("===>data_notif2 = "+data2.toString());

        showDialog(
          context: context,
          builder: (context) => AlertDialog(
            content: ListTile(
              title: Text(message['notification']['title']),
              subtitle: Text(message['notification']['body']),
            ),
            actions: <Widget>[
              FlatButton(
                child: Text('Ok'),
                onPressed: () => Navigator.of(context).pop(),
              ),
            ],
          ),
        );
      },
      onLaunch: (Map<String, dynamic> message) async {
        print("onLaunch: $message");
        // TODO optional
      },
      onResume: (Map<String, dynamic> message) async {
        print("onResume: $message");
        // TODO optional
      },
    );

    _saveDeviceToken();
  }

  /// Get the token, save it to the database for current user
  _saveDeviceToken() async {
    // Get the current user
    String uid = 'jeffd23';
    // FirebaseUser user = await _auth.currentUser();

    // Get the token for this device
    String fcmToken = await _firebaseMessaging.getToken();

    // Save it to Firestore
    if (fcmToken != null) {
      print(fcmToken);
    }
  }

和控制台输出

I/flutter (20959): onMessage: {notification: {title: Account Deposit, body: A deposit to your savings account has just cleared.}, data: {account: Savings, balance: $3020.25, link: https://somelink.com}}
I/flutter (20959): ===>data_notif2 = https://somelink.com

所以我相信问题出在你的代码中,而不是我给你的解决方案中。请清楚地寻找您可能遇到的问题。希望你能找到它并为你工作。


推荐阅读