firebase cloud messaging (FCM)
があり、ユーザーにメッセージを送信できます。
ただし、ユーザーが携帯電話で通知メッセージをタップすると、アプリがビューを開くかポップアップになり、バックグラウンドタスクを実行するというシナリオを作りたいと思います。
これは可能ですか?
ありがとうございました
=== Shady Boshraの提案に従って質問を更新
1)TypeScript
を使用してgoogleクラウド関数のfirebaseを作成します:
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):notification-{body:[TEST-123] body of message ...、title:[TEST-123] title ...}
I /フラッター(30602):データ-{}
I/flutter(30602):notification-{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.
ご覧のとおり、link
内のdata
の値を取得できません
もちろん、Flutterでも実行できます。
まず、マニフェストにこれらのコードを設定してください
<intent-filter> <action Android:name="FLUTTER_NOTIFICATION_CLICK" /> <category Android:name="Android.intent.category.DEFAULT" /> </intent-filter>
バックエンドのJSONの通知本文(node.js)にタグ要素を追加します。
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は、アプリが完全に終了した場合に発生します。
質問が更新されましたので、以下から検討してください 記事
•通知メッセージ-タイトルとメッセージ本文で構成され、デバイスに到着すると通知システムをトリガーします。つまり、ステータスバーにアイコンが表示され、通知シェードにエントリが表示されます。このような通知は、ユーザーに表示したい情報メッセージを送信するときに使用する必要があります。
例:
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" } };
ですから、通知とデータを同時に送信する3番目のものを使用すると思います。
以下のようにDartを使用してデータにアクセスできます。
message['data']['account']
あなたがあなたの質問を更新したとき、私の解決策はあなたとうまく機能しませんでした。私はそれを自分でテストすることに決めました、そして何を推測します!それはあなたと同じコードでうまくいきます。
私の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
だから私は問題が私にあなたに与える解決策ではなくあなたのコードに何らかの形であると信じています。発生する可能性のある問題を明確に探してください。あなたがそれを見つけて、うまくいくことを願っています。
はい、それはネイティブで可能ですが、私はフラッターではわかりません。バックスタックを使用して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
最も簡単な方法は、 OneSignal を使用していて、Firebaseを使用してプッシュ通知を送信するためのバックエンドを構築する十分な時間がない場合、ただし、OneSignalのサブスクライバーには制限があります(30,000サブスクライバーまで無料)。