颤振 - 用户打开推送通知消息(FCM)后如何执行任务
Posted
技术标签:
【中文标题】颤振 - 用户打开推送通知消息(FCM)后如何执行任务【英文标题】:flutter - How to do a task after user open push notif message (FCM) 【发布时间】:2019-12-30 05:32:37 【问题描述】:我有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;
,
然后我尝试在应用程序处于打开模式时发送推送通知。
但是,当我尝试调试它时,我找不到数据的内容。它返回以下响应:
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/flutter (30602):数据 -
I/flutter (30602): 通知 - body: [TEST-123] body of message... , title: [TEST-123] title...
I/flutter (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 的回答)
以下是我在 Flutter 上的代码:
_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.
如您所见,我无法在data
中获取link
的值
【问题讨论】:
尝试删除双引号,看看是否可行,data: picture: 'https://i.imgur.com/bY2bBGN.jpg', link: 'https://example.com'
@ShadyBoshra 如果我这样做,它会返回错误,请查看更新的问题(更新 2)...
试试这个data: 'picture' : 'https://i.imgur.com/bY2bBGN.jpg', 'link' : 'https://example.com'
,我在键前后添加了单个qoute
仍然错误:Type ' 'picture': string; 'link': string; ' is not assignable to type 'string'.
@ShadyBoshra 对不起,还没有。我明天会看到。谢谢……
【参考方案1】:
当然,你也可以在 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
,
);
我的大部分回答来自这个blog。
博客中提到了回调触发时,因此请仔细确定将代码设置在哪一个中。
onMessage 在应用打开并在前台运行时触发。
onResume 如果应用已关闭但仍在后台运行,则会触发。
onLaunch 在应用完全终止时触发。
更新
由于您的问题已更新,请从article 考虑以下内容
• 通知消息 - 由标题和消息正文和 到达设备时触发通知系统。其他 的话,状态栏中会出现一个图标,并会出现一个条目 在通知栏。此类通知应在以下情况下使用 发送您希望用户看到的信息性消息。
例如:
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
所以我相信问题出在你的代码中,而不是我给你的解决方案中。请清楚地寻找您可能遇到的问题。希望你能找到它并为你工作。
【讨论】:
我已经尝试了您的解决方案,但仍然没有使用nodejs
而是使用 firebase 控制台。我收到有关onMessage
状态的消息,但是对于onLaunch
和onResume
,我无法在调试控制台上得到它。有什么想法吗?
我更新了我的答案,请再次阅读,但是您将无法继续仅使用 Firebase 控制台,您应该继续使用后端 node.js 作为示例。
我在我的 Android 清单上有现有的 FLUTTER_NOTIFICATION_CLICK
意图。但它不起作用......
现在可以解决了,因为我之前的代码(firebase)使用的是typeScript
而不是javascript
哦,我明白了。祝你编码完美。【参考方案2】:
是的,在本机中是可能的,但我不确定是否会颤抖。 您可以使用返回堆栈构建 PendingIntent。
Intent notifIntent = new Intent(this, notifActivity.class);
TaskStackBuilder stkBuilder = TaskStackBuilder.create(this);
stkBuilder.addNextIntentWithParentStack(notifIntent);
PendingIntent resultPendingIntent =
stkBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
那么你应该将 PendingIntent 传递给通知。
检查此链接: https://developer.android.com/training/notify-user/navigation
【讨论】:
【参考方案3】:最简单的方法是使用OneSignal,如果你没有足够的时间来构建后端使用firebase发送推送通知,但是,OneSignal对他的订阅者有限制(免费直到30,000订阅者)。
【讨论】:
以上是关于颤振 - 用户打开推送通知消息(FCM)后如何执行任务的主要内容,如果未能解决你的问题,请参考以下文章