这是我的舱单:
<service android:name=".fcm.PshycoFirebaseMessagingServices">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<service android:name=".fcm.PshycoFirebaseInstanceIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
当应用程序在后台和通知到达,然后默认通知来,不运行我的onmessagerreceived代码。
这是我的onMessageReceived代码。如果我的应用程序在前台运行,而不是在后台运行,就会调用这个函数。我怎么能运行这段代码时,应用程序是在后台太?
// [START receive_message]
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// TODO(developer): Handle FCM messages here.
// If the application is in the foreground handle both data and notification messages here.
// Also if you intend on generating your own notifications as a result of a received FCM
// message, here is where that should be initiated. See sendNotification method below.
data = remoteMessage.getData();
String title = remoteMessage.getNotification().getTitle();
String message = remoteMessage.getNotification().getBody();
String imageUrl = (String) data.get("image");
String action = (String) data.get("action");
Log.i(TAG, "onMessageReceived: title : "+title);
Log.i(TAG, "onMessageReceived: message : "+message);
Log.i(TAG, "onMessageReceived: imageUrl : "+imageUrl);
Log.i(TAG, "onMessageReceived: action : "+action);
if (imageUrl == null) {
sendNotification(title,message,action);
} else {
new BigPictureNotification(this,title,message,imageUrl,action);
}
}
// [END receive_message]
1. 为什么会这样?
FCM (Firebase Cloud Messaging)中有两种类型的消息:
显示消息:这些消息仅在应用程序处于前台时触发onmessagerreceived()回调
数据消息:这些消息触发onmessagerreceived()回调,即使你的应用程序在前台/后台/被杀死
注意:Firebase团队还没有开发用于发送数据消息的UI
还有你的设备。您应该使用您的服务器发送这种类型!
2. 如何?
为了实现这一点,你必须对以下URL执行POST请求:
文章https://fcm.googleapis.com/fcm/send
头
关键字:Content-Type,值:application/json
Key: Authorization, Value: Key =<your-server-key>
主体使用主题
{
"to": "/topics/my_topic",
"data": {
"my_custom_key": "my_custom_value",
"my_custom_key2": true
}
}
或者如果你想把它发送到特定的设备
{
"data": {
"my_custom_key": "my_custom_value",
"my_custom_key2": true
},
"registration_ids": ["{device-token}","{device2-token}","{device3-token}"]
}
注意:请确保您没有添加JSON键通知
注意:要获得服务器密钥,您可以在firebase控制台中找到它:您的项目->设置->项目设置->云消息传递->服务器密钥
3.如何处理推送通知消息?
这是你如何处理收到的消息:
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Map<String, String> data = remoteMessage.getData();
String myCustomKey = data.get("my_custom_key");
// Manage data
}
我在firebase-messaging-sw.js中添加了以下代码,
messaging.onBackgroundmessage((payload)=>{
console.log("background message detected!!");
console.log("message : ", payload);
})
这是触发每次消息接收在后台。但我无法在主线程中使用有效负载,因为SW不支持它。所以我做了很多研究,在一个Android论坛上找到了一个解决方案。
因此,解决方案是必须从请求有效负载中删除通知有效负载。
所以我把有效载荷从
{
"notification": {
"title": "Hey there",
"body": "Subscribe to AMAL MOHAN N youtube channel"
},
"to": "your-browser-token",
"data": {
"value1": "text",
"value2": "",
"value3": "sample3",
"value4": "sample4"
}
}
to
{
"to": "your-browser-token",
"data": {
"value1": "text",
"value2": "",
"value3": "sample3",
"value4": "sample4"
}
}
有效负载的变化会自动在前台消息和后台消息中触发receiveMessage()。
我在一个Android论坛上发现了这个,这对我来说很有用!如果这对你有用,请告诉我。
根据文件显示,2017年5月17日
当你的应用在后台时,Android
将通知消息定向到系统托盘。用户轻按
通知默认打开应用程序启动器。
这包括同时包含通知和数据有效负载的消息
(以及从Notifications控制台发送的所有消息)。在这些
在情况下,通知被传递到设备的系统托盘,和
数据有效负载是在您的意图的附加部分中交付的
发射器的活动。
所以,你应该同时使用有效负载通知和数据:
{
"to": "FCM registration ID",
"notification": {
"title" : "title",
"body" : "body text",
"icon" : "ic_notification"
},
"data": {
"someData" : "This is some data",
"someData2" : "etc"
}
}
不需要使用click_action。你应该从LAUNCHER活动中获得额外的意图
<activity android:name=".MainActivity">
<intent-filter>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Java代码应该在MainActivity的onCreate方法上:
Intent intent = getIntent();
if (intent != null && intent.getExtras() != null) {
Bundle extras = intent.getExtras();
String someData= extras.getString("someData");
String someData2 = extras.getString("someData2");
}
您可以从Firebase Notifications Console测试有效负载通知+数据。不要忘记在高级选项部分填写自定义数据字段
要在后台捕获消息,您需要使用BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.util.Log
import androidx.legacy.content.WakefulBroadcastReceiver
import com.google.firebase.messaging.RemoteMessage
class FirebaseBroadcastReceiver : WakefulBroadcastReceiver() {
val TAG: String = FirebaseBroadcastReceiver::class.java.simpleName
override fun onReceive(context: Context, intent: Intent) {
val dataBundle = intent.extras
if (dataBundle != null)
for (key in dataBundle.keySet()) {
Log.d(TAG, "dataBundle: " + key + " : " + dataBundle.get(key))
}
val remoteMessage = RemoteMessage(dataBundle)
}
}
把这个加到你的舱单上
<receiver
android:name="MY_PACKAGE_NAME.FirebaseBroadcastReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</receiver>
根据firebase文档在发送下游使用firebase,有两种类型的有效载荷:
数据
此参数指定消息有效负载的自定义键-值对。
客户端应用程序负责处理数据消息。数据消息只有自定义键值对。
通知
此参数指定通知有效负载的预定义的、用户可见的键-值对。FCM自动代表客户端应用程序将消息显示给最终用户设备。通知消息具有一组预定义的用户可见键。
当你在前台时,你可以使用onmessagerecreceived()在FCM内部获取数据,你可以从数据有效载荷中获取数据。
data = remoteMessage.getData();
String customData = (String) data.get("customData");
当您在后台时,FCM将根据通知有效载荷的信息在系统托盘中显示通知。系统托盘上用于通知的标题、消息和图标都来自通知有效负载。
{
"notification": {
"title" : "title",
"body" : "body text",
"icon" : "ic_notification",
"click_action" : "OPEN_ACTIVITY_1"
}
}
当你想在应用程序处于后台时自动在系统托盘上显示通知时,使用这个通知有效载荷。
当你的应用程序在后台运行时,为了获得通知数据,你应该在通知有效载荷中添加click_action。
如果你想打开你的应用并执行一个特定的动作(在后台),在通知有效载荷中设置click_action,并将其映射到你想要启动的Activity中的意图过滤器。例如,将click_action设置为OPEN_ACTIVITY_1来触发一个意图过滤器,如下所示:
<intent-filter>
<action android:name="OPEN_ACTIVITY_1" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
把intent-filter放在你的清单上,在你的一个activity标签里面。当你点击通知时,它将打开应用程序并直接进入你在click_action中定义的活动,在本例中为“OPEN_ACTIVTY_1”。
在这个活动中,你可以通过以下方式获取数据:
Bundle b = getIntent().getExtras();
String someData = b.getString("someData");
我使用FCM为我的android应用程序和使用两个有效载荷。
下面是我使用的JSON示例:
{
"to": "FCM registration ID",
"notification": {
"title" : "title",
"body" : "body text",
"icon" : "ic_notification",
"click_action" : "OPEN_ACTIVITY_1"
},
"data": {
"someData" : "This is some data",
"someData2" : "etc"
}
}
要使firebase库在以下情况下调用onmessagerecreceived ()
应用程序在前台
后台应用程序
应用程序已被杀死
你不能把JSON键通知在你的请求到Firebase API,而是使用数据,见下文。
当你的应用程序处于后台或被杀死时,下面的消息将不会调用你的onmessagerreceived(),并且你不能自定义你的通知。
{
"to": "/topics/journal",
"notification": {
"title" : "title",
"text": "data!",
"icon": "ic_notification"
}
}
但是用这个方法就可以了
{
"to": "/topics/dev_journal",
"data": {
"text":"text",
"title":"",
"line1":"Journal",
"line2":"刊物"
}
}
基本上,消息是在参数RemoteMessage中与数据对象一起发送的,如Map<String, String>,然后您可以在这里的代码片段中管理onmessagerreceived中的通知
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Map<String, String> data = remoteMessage.getData();
//you can get your text message here.
String text= data.get("text");
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
// optional, this is to make beautiful icon
.setLargeIcon(BitmapFactory.decodeResource(
getResources(), R.mipmap.ic_launcher))
.setSmallIcon(smallIcon) //mandatory
.......
/*You can read more on notification here:
https://developer.android.com/training/notify-user/build-notification.html
https://www.youtube.com/watch?v=-iog_fmm6mE
*/
}