当应用程序在后台时,当用户单击通知时,我正在尝试打开特定活动。从文档中,我知道 click_action 必须添加到有效负载中,并在应用程序中添加一个意图过滤器来处理它。但是,如何通过 Firebase 控制台在 Firebase 通知中添加 click_action?我也对任何其他的 Workaround 持开放态度。提前致谢。
12 回答
如果您的应用在后台,Firebase 将不会触发 onMessageReceived()。为什么.....?我不知道。在这种情况下,我认为实施 FirebaseMessagingService 没有任何意义。
根据文档,如果要处理后台消息到达,则必须随消息发送“click_action”。但是,如果您仅通过 Firebase API 从 Firebase 控制台发送消息,则这是不可能的。这意味着您必须建立自己的“控制台”才能使营销人员使用它。因此,这使得 Firebase 控制台也毫无用处!
这个新工具背后确实有很好的、有前途的想法,但执行得很糟糕。
我想我们将不得不等待新版本和改进/修复!
据我所知,此时无法在控制台中设置 click_action。
虽然对于如何在控制台中设置 click_action 不是一个严格的答案,但您可以使用 curl 作为替代方案:
curl --header "Authorization: key=<YOUR_KEY_GOES_HERE>" --header Content-Type:"application/json" https://fcm.googleapis.com/fcm/send -d "{\"to\":\"/topics/news\",\"notification\": {\"title\": \"Click Action Message\",\"text\": \"Sample message\",\"click_action\":\"OPEN_ACTIVITY_1\"}}"
这是测试 click_action 映射的简单方法。它需要一个类似 FCM 文档中指定的意图过滤器:
<intent-filter>
<action android:name="OPEN_ACTIVITY_1" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
这也利用话题来设置受众。为了使它起作用,您需要订阅一个名为“新闻”的主题。
FirebaseMessaging.getInstance().subscribeToTopic("news");
即使在控制台中看到一个新创建的主题需要几个小时,您仍然可以通过 FCM api 向它发送消息。
另外,请记住,这仅在应用程序在后台时才有效。如果它在前台,您将需要实现 FirebaseMessagingService 的扩展。在 onMessageReceived 方法中,您需要手动导航到 click_action 目标:
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
//This will give you the topic string from curl request (/topics/news)
Log.d(TAG, "From: " + remoteMessage.getFrom());
//This will give you the Text property in the curl request(Sample Message):
Log.d(TAG, "Notification Message Body: " + remoteMessage.getNotification().getBody());
//This is where you get your click_action
Log.d(TAG, "Notification Click Action: " + remoteMessage.getNotification().getClickAction());
//put code here to navigate based on click_action
}
正如我所说,目前我找不到通过控制台访问通知有效负载属性的方法,但我认为这种解决方法可能会有所帮助。
您可以在扩展 FirebaseMessagingService 的服务中处理 onMessageReceived() 中的消息功能中的所有操作。为此,您必须发送仅包含数据的消息,例如使用Chrome 中的高级 REST 客户端。 然后,您使用“原始标题”向https://fcm.googleapis.com/fcm/send发送 POST :
内容类型:application/json 授权:key=YOUR_PERSONAL_FIREBASE_WEB_API_KEY
以及“原始有效负载”字段中的 json 消息。
警告,如果您的 json 中有“通知”字段,则在 onMessageReceived() 中的应用程序在后台时将永远不会收到您的消息,即使有数据字段!例如,这样做,消息仅在应用程序处于前台时才起作用:
{
"condition": " 'Symulti' in topics || 'SymultiLite' in topics",
"priority" : "normal",
"time_to_live" : 0,
"notification" : {
"body" : "new Symulti update !",
"title" : "new Symulti update !",
"icon" : "ic_notif_symulti"
},
"data" : {
"id" : 1,
"text" : "new Symulti update !"
}
}
为了在 onMessageReceived() 中的所有情况下都能收到您的消息,只需从您的 json 中删除“通知”字段!
例子:
{
"condition": " 'Symulti' in topics || 'SymultiLite' in topics",
"priority" : "normal",
"time_to_live" : 0,,
"data" : {
"id" : 1,
"text" : "new Symulti update !",
"link" : "href://www.symulti.com"
}
}
在您的 FirebaseMessagingService 中:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
String message = "";
obj = remoteMessage.getData().get("text");
if (obj != null) {
try {
message = obj.toString();
} catch (Exception e) {
message = "";
e.printStackTrace();
}
}
String link = "";
obj = remoteMessage.getData().get("link");
if (obj != null) {
try {
link = (String) obj;
} catch (Exception e) {
link = "";
e.printStackTrace();
}
}
Intent intent;
PendingIntent pendingIntent;
if (link.equals("")) { // Simply run your activity
intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
} else { // open a link
String url = "";
if (!link.equals("")) {
intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(link));
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
}
}
pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder notificationBuilder = null;
try {
notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_notif_symulti) // don't need to pass icon with your message if it's already in your app !
.setContentTitle(URLDecoder.decode(getString(R.string.app_name), "UTF-8"))
.setContentText(URLDecoder.decode(message, "UTF-8"))
.setAutoCancel(true)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setContentIntent(pendingIntent);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
if (notificationBuilder != null) {
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(id, notificationBuilder.build());
} else {
Log.d(TAG, "error NotificationManager");
}
}
}
}
享受 !
这属于解决方法类别,也包含一些额外的信息:
由于根据应用程序的状态(前台/后台/未启动)处理通知的方式不同,我已经看到了实现帮助程序类的最佳方法,其中根据通知消息中发送的自定义数据启动选定的活动。
- 当应用程序处于前台时,使用 onMessageReceived 中的帮助程序类
- 当应用程序处于后台时,使用辅助类来处理主要活动的 onNewIntent 中的意图(检查特定的自定义数据)
- 当应用程序未运行时,使用辅助类来处理主要活动的 onCreate 中的意图(调用 getIntent 获取意图)。
这样您就不需要 click_action 或特定于它的意图过滤器。此外,您只需编写一次代码,就可以相当容易地启动任何活动。
所以最小的自定义数据看起来像这样:
Key: run_activity
Value: com.mypackage.myactivity
以及处理它的代码:
if (intent.hasExtra("run_activity")) {
handleFirebaseNotificationIntent(intent);
}
private void handleFirebaseNotificationIntent(Intent intent){
String className = intent.getStringExtra("run_activity");
startSelectedActivity(className, intent.getExtras());
}
private void startSelectedActivity(String className, Bundle extras){
Class cls;
try {
cls = Class.forName(className);
}catch(ClassNotFoundException e){
...
}
Intent i = new Intent(context, cls);
if (i != null) {
i.putExtras(extras);
this.startActivity(i);
}
}
这是最后两种情况的代码,startSelectedActivity 也会从 onMessageReceived (第一种情况)中调用。
限制是 Intent Extras 中的所有数据都是字符串,因此您可能需要在 Activity 本身中以某种方式处理它。此外,这是简化的,您可能不会在不警告用户的情况下更改前台应用程序的活动/视图。
好吧,从 firebase 文档中可以清楚地看出,onMessageReceived
当应用程序处于后台时,您将无法工作。
当您的应用程序处于后台并单击通知时,您的默认启动器将启动。要启动所需的活动,您需要click_action
在通知有效负载中指定。
$noti = array
(
'icon' => 'new',
'title' => 'title',
'body' => 'new msg',
'click_action' => 'your activity name comes here'
);
在你的android.manifest
文件中
在您注册活动的位置添加以下代码
<activity
android:name="your activity name">
<intent-filter>
<action android:name="your activity name" />
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
如果您的应用在后台,Firebase 将不会触发 onMessageReceived()。当应用程序处于前台时调用 onMessageReceived()。当应用程序处于后台时,仅当https://fcm.googleapis.com/fcm/send的正文仅包含数据有效负载时才会调用 onMessageReceived() 方法。在这里,我刚刚创建了一个方法来构建具有意图的自定义通知您需要的活动。并在 onMessageRecevied() 中调用此方法。
在邮递员中:
网址:https ://fcm.googleapis.com/fcm/send
标头:授权:密钥=您的密钥
身体--->>
{ "data" : {
"Nick" : "Mario",
"Room" : "PoSDenmark",
},
"to" : "xxxxxxxxx"
}
在您的应用程序中。
class MyFirebaseMessagingService extends FirebaseMessagingService {
public void onMessageReceived(RemoteMessage remoteMessage) {
if (remoteMessage.getData().size() > 0) {
sendNotification("ur message body") ;
}
}
private void sendNotification(String messageBody) {
Intent intent = new Intent(this, Main2Activity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_stat_ic_notification)
.setContentTitle("FCM Message")
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
}
当数据有效负载到达移动设备时,将调用 onMessageReceived() 方法。在该方法中,我只是做了一个自定义通知。即使您的应用程序是后台或前台,这也将起作用。
更新:
所以只是为了验证,目前无法click_action
通过 Firebase 控制台设置参数。
所以我一直在尝试在 Firebase 通知控制台中执行此操作,但没有成功。由于我似乎找不到click_action
在控制台中放置值的任何地方,所以我主要做的是在通知中添加一个自定义键/值对(高级选项>自定义数据):
Key: click_action
Value: <your_preferred_value>
然后尝试调用RemoteMessage.getNotification().getClickAction()以onMessageReceived()
查看它是否正在检索正确的值,但它总是返回null
。所以接下来我尝试调用RemoteMessage.getData().get(< specified_key >)并能够检索我添加的值。
注意:我不完全确定这是否可以用作解决方法,或者它是否违反最佳实践。我建议使用您自己的应用服务器,但您的帖子特定于 Firebase 控制台。
客户端应用程序和通知的行为方式仍然取决于您如何对其进行编程。话虽如此,我认为您可以使用上述方法作为解决方法,使用从 检索到的值getData()
,然后让 Notification 调用这个或那个。希望这会有所帮助。干杯! :D
在 Web 中,只需添加要打开的 url:
{
"condition": "'test-topic' in topics || 'test-topic-2' in topics",
"notification": {
"title": "FCM Message with condition and link",
"body": "This is a Firebase Cloud Messaging Topic Message!",
"click_action": "https://yoururl.here"
}
}
现在可以在 Firebase 控制台中设置 click_action。您只需转到通知-发送消息-高级选项,您将有两个字段用于键和值。在第一个字段中放置 click_action,在第二个字段中放置一些代表该操作值的文本。然后在 Manifest 中添加意图过滤器,并为他提供与您在控制台中编写的相同的值。那是真实click_action的模拟。
一个简单的解决方法是,在 fcm 选项中 - 添加/
为链接值,背景通知单击将被重定向到应用程序。
fcm fcm 消息通知和应用程序通知有双重方法,首先您的应用程序接收器只有带有正文、标题的消息通知,您可以添加颜色、振动不起作用、声音默认。在第二个中,您可以完全控制收到消息示例时发生的情况,
onMessageReciever(RemoteMessage rMessage){ notification.setContentTitle(rMessage.getData().get("yourKey")); }
您将使用(yourKey)接收数据,但不是来自 fcm 云功能 reguard 的 fcm 消息
我在看这个 Firebase 是从谷歌云消息推送通知基础开发的,所以我们可以使用 gcm 教程、firebase 中的功能和实现,我使用 gcm 推送通知功能的功能来解决这个 click_action 问题我使用 gcm 功能**
'通知点击'
** 试试这个在server-worker.js中的变量url中保存 url click_action
var url = "";
messaging.setBackgroundMessageHandler(function(payload) {
console.log('[firebase-messaging-sw.js] Received background message ', payload);
// Customize notification here
url = payload.data.click_action;
const notificationTitle = payload.data.title;
const notificationOptions = {
body: payload.data.body ,
icon: 'firebase-logo.png'
};
return self.registration.showNotification(notificationTitle,
notificationOptions);
});
//i got this in google cloud messaging push notification
self.addEventListener('notificationclick', function (event) {
event.notification.close();
var clickResponsePromise = Promise.resolve();
clickResponsePromise = clients.openWindow(url);
event.waitUntil(Promise.all([clickResponsePromise, self.analytics.trackEvent('notification-click')]));
});