提问人:Cyogenos 提问时间:5/21/2016 最后编辑:Frank van PuffelenCyogenos 更新时间:5/30/2023 访问量:283047
Firebase onMessageReceived 在后台应用时未调用
Firebase onMessageReceived not called when app in background
问:
我正在使用 Firebase,并测试在应用处于后台时从我的服务器向我的应用发送通知。通知发送成功,甚至出现在设备的通知中心,但是当通知出现时,或者即使我单击它,也不会调用我的 FCMessagingService 中的 onMessageReceived 方法。
当我的应用程序在前台时测试它时,调用了 onMessageReceived 方法,一切正常。当应用程序在后台运行时,会出现此问题。
这是预期的行为,还是有办法解决这个问题?
这是我的FBMessagingService:
import android.util.Log;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
public class FBMessagingService extends FirebaseMessagingService {
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.i("PVL", "MESSAGE RECEIVED!!");
if (remoteMessage.getNotification().getBody() != null) {
Log.i("PVL", "RECEIVED MESSAGE: " + remoteMessage.getNotification().getBody());
} else {
Log.i("PVL", "RECEIVED MESSAGE: " + remoteMessage.getData().get("message"));
}
}
}
答:
我遇到了这个问题(如果应用程序在后台或已关闭,应用程序不想在通知单击时打开),并且问题是通知正文中无效,请尝试将其删除或更改为有效内容。click_action
这按预期工作,仅当您的应用处于前台时,通知消息才会发送到您的 onMessageReceived 回调。如果您的应用处于后台或已关闭状态,则通知中心会显示一条通知消息,并且该消息中的所有数据都会传递到因用户点击通知而启动的 Intent。
您可以在 JSON 中指定 a,以指示在用户点击通知时应启动的 intent。如果未指定click_action,则使用主活动。click_action
启动 intent 后,您可以使用
getIntent().getExtras();
检索一个 Set,该 Set 将包含与通知消息一起发送的任何数据。
有关通知消息的更多信息,请参阅文档。
评论
click_action
我也有同样的问题。使用“数据消息”而不是“通知”更容易。数据消息始终加载类 onMessageReceived。
在该类中,您可以使用通知生成器制作自己的通知。
例:
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
sendNotification(remoteMessage.getData().get("title"),remoteMessage.getData().get("body"));
}
private void sendNotification(String messageTitle,String messageBody) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0 /* request code */, intent,PendingIntent.FLAG_UPDATE_CURRENT);
long[] pattern = {500,500,500,500,500};
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_stat_name)
.setContentTitle(messageTitle)
.setContentText(messageBody)
.setAutoCancel(true)
.setVibrate(pattern)
.setLights(Color.BLUE,1,1)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
评论
根据 Firebase Cloud Messaging 文档 - 如果 Activity 在前台,则将调用 onMessageReceived。如果活动处于后台或已关闭状态,则通知消息会显示在应用启动器活动的通知中心中。 如果您的应用处于后台状态,您可以通过调用 REST Service API for firebase messaging 来调用自定义活动,如下所示:
URL-https://fcm.googleapis.com/fcm/send
方法类型 - POST
Header- Content-Type:application/json
Authorization:key=your api key
车身/有效载荷:
{ "notification": {
"title": "Your Title",
"text": "Your Text",
"click_action": "OPEN_ACTIVITY_1" // should match to your intent filter
},
"data": {
"keyname": "any value " //you can get this data as extras in your activity and this data is optional
},
"to" : "to_id(firebase refreshedToken)"
}
在您的应用程序中使用它,您可以在要调用的活动中添加以下代码:
<intent-filter>
<action android:name="OPEN_ACTIVITY_1" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
评论
onMessageReceived
默认情况下,当您的应用程序处于后台并单击通知时,您的应用程序中的启动器活动将启动,如果您有任何数据部分的通知,您可以在相同的活动中处理它,如下所示:
if(getIntent().getExtras()! = null){
//do your stuff
}else{
//do that you normally do
}
评论
我遇到了同样的问题,并对此进行了更多挖掘。当应用程序在后台时,通知消息会发送到系统托盘,但会向
See https://firebase.google.com/docs/cloud-messaging/downstream#monitor-token-generation_3
和 https://github.com/firebase/quickstart-android/blob/master/messaging/app/src/main/java/com/google/firebase/quickstart/fcm/MyFirebaseMessagingService.java 发送数据消息onMessageReceived()
为确保您发送的消息,文档会说:“使用您的应用服务器和 FCM 服务器 API:仅设置数据密钥。可以是可折叠的,也可以是不可折叠的。
查看 https://firebase.google.com/docs/cloud-messaging/concept-options#notifications_and_data_messages
消息有两种类型:通知消息和数据消息。 如果仅发送数据消息,则消息字符串中没有通知对象。当您的应用程序在后台时,将调用它。
以下是有关 firebase 消息的更清晰概念。我是从他们的支持团队那里找到的。
Firebase 有三种消息类型:
通知消息:通知消息在后台或前台工作。当应用程序处于后台时,通知消息将传递到系统托盘。如果应用位于前台,则消息由 或 回调处理。这些实质上就是所谓的显示消息。onMessageReceived()
didReceiveRemoteNotification
数据消息:在Android平台上,数据消息可以在后台和前台工作。数据消息将由 onMessageReceived() 处理。此处特定于平台的说明如下:在 Android 上,可以在用于启动活动的 Intent 中检索数据有效负载。详细地说,如果有 ,则只能从 中检索此意图。"click_action":"launch_Activity_1"
getIntent()
Activity_1
同时包含通知和数据负载的消息:在后台时,应用会在通知托盘中接收通知有效负载,并且仅在用户点击通知时处理数据负载。在前台时,您的应用会收到一个消息对象,其中包含两个可用的有效负载。其次,click_action参数通常用于通知负载,而不是数据负载。如果在数据负载中使用,此参数将被视为自定义键值对,因此您需要实现自定义逻辑才能使其按预期工作。
另外,我建议您使用 onMessageReceived 方法(请参阅数据消息)来提取数据包。根据您的逻辑,我检查了捆绑包对象,但没有找到预期的数据内容。这里引用了一个类似的案例,可能会提供更清晰的信息。
从服务器端来看,firebase 通知的格式应如下:
服务器端应发送“通知”对象。我缺少“通知”对象,没有收到消息。TargetActivity
getIntent()
正确的消息格式如下:
{
"data": {
"body": "here is body",
"title": "Title"
},
"notification": {
"body": "here is body",
"title": "Title",
"click_action": "YOUR_ACTION"
},
"to": "ffEseX6vwcM:APA91bF8m7wOF MY FCM ID 07j1aPUb"
}
欲了解更多信息,请访问 https://stackoverflow.com/a/39805517
评论
值得强调的一点是,即使应用程序在后台,您也必须使用数据消息(仅数据键)来调用 onMessageReceived 处理程序。有效负载中不应有任何其他通知消息密钥,否则,如果应用处于后台状态,则不会触发处理程序。
这里提到了(但在 FCM 文档中没有强调):
https://firebase.google.com/docs/cloud-messaging/concept-options#notifications_and_data_messages
使用应用服务器和 FCM 服务器 API:仅设置数据密钥。可以是 可折叠或不可折叠。
从服务器请求中完全删除通知
字段。仅发送数据
并对其进行处理,否则当应用程序处于后台或被杀死时,您将不会被触发。onMessageReceived()
onMessageReceived()
不要忘记在通知请求中包含字段。根据文档:数据消息以正常优先级发送,因此它们不会立即到达;这也可能是问题所在。"priority": "high"
这是我从服务器发送的内容
{
"data":{
"id": 1,
"missedRequests": 5
"addAnyDataHere": 123
},
"to": "fhiT7evmZk8:APA91bFJq7Tkly4BtLRXdYvqHno2vHCRkzpJT8QZy0TlIGs......",
"priority": "high"
}
因此,您可以像这样接收数据。假设我必须获得 idonMessageReceived(RemoteMessage message)
Object obj = message.getData().get("id");
if (obj != null) {
int id = Integer.valueOf(obj.toString());
}
评论
我正在使用的后端使用的是通知消息,而不是数据消息。因此,在阅读了所有答案后,我试图从启动活动的意图捆绑包中检索额外内容。
但无论我尝试从哪个键中检索,该值始终为 null。getIntent().getExtras();
但是,我终于找到了一种使用通知消息发送数据并从意图中检索数据的方法。
这里的关键是将数据有效负载添加到通知消息中。
例:
{
"data": {
"message": "message_body",
"title": "message_title"
},
"notification": {
"body": "test body",
"title": "test title"
},
"to": "E4An.."
}
执行此操作后,您将能够通过以下方式获取您的信息:
intent.getExtras().getString("title")
将是message_title
并将intent.getExtras().getString("message")
message_body
只需在 MainActivity 的 onCreate 方法中调用它:
if (getIntent().getExtras() != null) {
// Call your NotificationActivity here..
Intent intent = new Intent(MainActivity.this, NotificationActivity.class);
startActivity(intent);
}
评论
如果应用程序处于后台模式或非活动(已杀),并且您单击通知,则应检查 LaunchScreen 中的有效负载(在我的情况下,启动屏幕是 MainActivity.java)。
因此,在 MainActivity 中.java在 onCreate 上检查 Extras:
if (getIntent().getExtras() != null) {
for (String key : getIntent().getExtras().keySet()) {
Object value = getIntent().getExtras().get(key);
Log.d("MainActivity: ", "Key: " + key + " Value: " + value);
}
}
评论
如果您的问题与显示大图像有关,即如果您从 firebase 控制台发送带有图像的推送通知,并且仅当应用程序在前台时才会显示图像。此问题的解决方案是发送仅包含数据字段的推送消息。像这样的东西:
{ "data": { "image": "https://static.pexels.com/photos/4825/red-love-romantic-flowers.jpg", "message": "Firebase Push Message Using API" "AnotherActivity": "True" }, "to" : "device id Or Device token" }
评论
此方法 handleIntent() 已弃用,因此可以按如下方式处理通知:
前台状态:单击通知将转到您在按语法创建通知时提供的待处理 Intent 活动,因为它通常使用通知的数据负载创建。
后台/终止状态 - 在这里,系统本身会根据通知有效负载创建通知,单击该通知将带您进入应用程序的启动器活动,您可以在其中轻松获取任何生命周期方法中的 Intent 数据。
评论
OnMessageReceived
为我覆盖作品的方法。handleIntent
FirebaseMessageService
这里是 C# (Xamarin) 中的代码
public override void HandleIntent(Intent intent)
{
try
{
if (intent.Extras != null)
{
var builder = new RemoteMessage.Builder("MyFirebaseMessagingService");
foreach (string key in intent.Extras.KeySet())
{
builder.AddData(key, intent.Extras.Get(key).ToString());
}
this.OnMessageReceived(builder.Build());
}
else
{
base.HandleIntent(intent);
}
}
catch (Exception)
{
base.HandleIntent(intent);
}
}
这就是 Java 代码
public void handleIntent(Intent intent)
{
try
{
if (intent.getExtras() != null)
{
RemoteMessage.Builder builder = new RemoteMessage.Builder("MyFirebaseMessagingService");
for (String key : intent.getExtras().keySet())
{
builder.addData(key, intent.getExtras().get(key).toString());
}
onMessageReceived(builder.build());
}
else
{
super.handleIntent(intent);
}
}
catch (Exception e)
{
super.handleIntent(intent);
}
}
评论
根据 t3h Exi 的解决方案,我想在这里发布干净的代码。只需将其放入 MyFirebaseMessagingService 中,如果应用程序处于后台模式,一切正常。您至少需要编译 com.google.firebase:firebase-messaging:10.2.1
@Override
public void handleIntent(Intent intent)
{
try
{
if (intent.getExtras() != null)
{
RemoteMessage.Builder builder = new RemoteMessage.Builder("MyFirebaseMessagingService");
for (String key : intent.getExtras().keySet())
{
builder.addData(key, intent.getExtras().get(key).toString());
}
onMessageReceived(builder.build());
}
else
{
super.handleIntent(intent);
}
}
catch (Exception e)
{
super.handleIntent(intent);
}
}
评论
我遇到了同样的问题。如果应用是前台 - 它会触发我的后台服务,我可以在其中根据通知类型更新我的数据库。 但是,应用程序会进入后台 - 默认通知服务将负责向用户显示通知。
这是我的解决方案,用于在后台识别应用程序并触发后台服务,
public class FirebaseBackgroundService extends WakefulBroadcastReceiver {
private static final String TAG = "FirebaseService";
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "I'm in!!!");
if (intent.getExtras() != null) {
for (String key : intent.getExtras().keySet()) {
Object value = intent.getExtras().get(key);
Log.e("FirebaseDataReceiver", "Key: " + key + " Value: " + value);
if(key.equalsIgnoreCase("gcm.notification.body") && value != null) {
Bundle bundle = new Bundle();
Intent backgroundIntent = new Intent(context, BackgroundSyncJobService.class);
bundle.putString("push_message", value + "");
backgroundIntent.putExtras(bundle);
context.startService(backgroundIntent);
}
}
}
}
}
在清单 .xml 中
<receiver android:exported="true" android:name=".FirebaseBackgroundService" android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</receiver>
在最新的android 8.0版本中测试了此解决方案。谢谢
评论
WakefulBroadcastReceiver
自 API 级别 26.1.0 起已弃用。
如果应用程序在后台 Fire-base 默认处理通知,但是如果我们想要自定义通知,则必须更改我们的服务器端,该端负责发送我们的自定义数据(数据有效负载)
从服务器请求中完全删除通知有效负载。仅发送数据并在 onMessageReceived() 中处理它,否则当应用程序处于后台或被终止时,您的 onMessageReceived 将不会被触发。
现在,你的服务器端代码格式是这样的,
{
"collapse_key": "CHAT_MESSAGE_CONTACT",
"data": {
"loc_key": "CHAT_MESSAGE_CONTACT",
"loc_args": ["John Doe", "Contact Exchange"],
"text": "John Doe shared a contact in the group Contact Exchange",
"custom": {
"chat_id": 241233,
"msg_id": 123
},
"badge": 1,
"sound": "sound1.mp3",
"mute": true
}
}
注意:请参阅上面代码
“text”中的这一行:“John Doe 在组 Contact Exchange 中共享了一个联系人”
在数据有效负载中,您应该使用“text”参数而不是“body”或“message”参数来描述消息描述或任何您想要使用的文本。
onMessageReceived()
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.e(TAG, "From: " + remoteMessage.getData().toString());
if (remoteMessage == null)
return;
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
/* Log.e(TAG, "Data Payload: " + remoteMessage.getData().toString());*/
Log.e(TAG, "Data Payload: " + remoteMessage);
try {
Map<String, String> params = remoteMessage.getData();
JSONObject json = new JSONObject(params);
Log.e("JSON_OBJECT", json.toString());
Log.e(TAG, "onMessageReceived: " + json.toString());
handleDataMessage(json);
} catch (Exception e) {
Log.e(TAG, "Exception: " + e.getMessage());
}
}
}
试试这个:
public void handleIntent(Intent intent) {
try {
if (intent.getExtras() != null) {
RemoteMessage.Builder builder = new RemoteMessage.Builder("MyFirebaseMessagingService");
for (String key : intent.getExtras().keySet()) {
builder.addData(key, intent.getExtras().get(key).toString());
}
onMessageReceived(builder.build());
} else {
super.handleIntent(intent);
}
} catch (Exception e) {
super.handleIntent(intent);
}
}
祝你好运
评论
当收到消息并且您的应用处于后台时,通知将发送到主要活动的额外意图。
您可以在主活动的 oncreate() 或 onresume() 函数中检查额外的值。
您可以检查数据、表格等字段(通知中指定的字段)
例如,我使用数据作为密钥发送
public void onResume(){
super.onResume();
if (getIntent().getStringExtra("data")!=null){
fromnotification=true;
Intent i = new Intent(MainActivity.this, Activity2.class);
i.putExtra("notification","notification");
startActivity(i);
}
}
Firebase 推送通知有 2 种类型:
1-通知消息(显示消息)->
-- 1.1 如果您选择此变体,如果应用程序处于后台,操作系统将自行创建通知,并将数据传递到 .然后由客户端来处理这些数据。intent
-- 1.2 如果应用程序在前台,则它将通过 在 中接收通知,并由客户端来处理它。callback-function
FirebaseMessagingService
2- 数据消息(最多 4k 数据) -> 这些消息仅用于向客户端发送数据(静默),并且由客户端通过 callback-function 在后台/前台两种情况下处理它FirebaseMessagingService
这是根据官方文档:https://firebase.google.com/docs/cloud-messaging/concept-options
onMessageReceived(RemoteMessage remoteMessage) 方法基于以下情况调用。
- FCM 响应使用通知和数据块:
{
"to": "device token list",
"notification": {
"body": "Body of Your Notification",
"title": "Title of Your Notification"
},
"data": {
"body": "Body of Your Notification in Data",
"title": "Title of Your Notification in Title",
"key_1": "Value for key_1",
"image_url": "www.abc.com/xyz.jpeg",
"key_2": "Value for key_2"
}
}
- 前台应用:
onMessageReceived(RemoteMessage remoteMessage) 调用,在通知栏中显示 LargeIcon 和 BigPicture。我们可以从通知和数据块中读取内容
- 后台应用:
onMessageReceived(RemoteMessage remoteMessage) 未调用,系统托盘将接收消息并读取通知块中的正文和标题,并在通知栏中显示默认消息和标题。
- FCM 响应仅使用数据块:
在这种情况下,请从 json 中删除通知块
{
"to": "device token list",
"data": {
"body": "Body of Your Notification in Data",
"title": "Title of Your Notification in Title",
"key_1": "Value for key_1",
"image_url": "www.abc.com/xyz.jpeg",
"key_2": "Value for key_2"
}
}
调用 onMessageReceived() 的解决方案
- 前台应用:
onMessageReceived(RemoteMessage remoteMessage) 调用,在通知栏中显示 LargeIcon 和 BigPicture。我们可以从通知和数据块中读取内容
- 后台应用:
onMessageReceived(RemoteMessage remoteMessage) 调用,系统托盘不会收到消息,因为通知键不在响应中。在通知栏中显示 LargeIcon 和 BigPicture
法典
private void sendNotification(Bitmap bitmap, String title, String
message, PendingIntent resultPendingIntent) {
NotificationCompat.BigPictureStyle style = new NotificationCompat.BigPictureStyle();
style.bigPicture(bitmap);
Uri defaultSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
String NOTIFICATION_CHANNEL_ID = mContext.getString(R.string.default_notification_channel_id);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "channel_name", NotificationManager.IMPORTANCE_HIGH);
notificationManager.createNotificationChannel(notificationChannel);
}
Bitmap iconLarge = BitmapFactory.decodeResource(mContext.getResources(),
R.drawable.mdmlogo);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(mContext, NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.drawable.mdmlogo)
.setContentTitle(title)
.setAutoCancel(true)
.setSound(defaultSound)
.setContentText(message)
.setContentIntent(resultPendingIntent)
.setStyle(style)
.setLargeIcon(iconLarge)
.setWhen(System.currentTimeMillis())
.setPriority(Notification.PRIORITY_MAX)
.setChannelId(NOTIFICATION_CHANNEL_ID);
notificationManager.notify(1, notificationBuilder.build());
}
参考链接:
https://firebase.google.com/docs/cloud-messaging/android/receive
评论
检查@Mahesh Kavathiya的答案。就我而言,在服务器代码中只有这样的:
{
"notification": {
"body": "here is body",
"title": "Title",
},
"to": "sdfjsdfonsdofoiewj9230idsjkfmnkdsfm"
}
您需要更改为:
{
"data": {
"body": "here is body",
"title": "Title",
"click_action": "YOUR_ACTION"
},
"notification": {
"body": "here is body",
"title": "Title"
},
"to": "sdfjsdfonsdofoiewj9230idsjkfmnkdsfm"
}
然后,如果应用程序在后台,默认活动意图额外将获取“数据”
祝你好运!
我有类似的问题。根据本页中提到的答案和参考资料,以下是我如何通过以下方法解决问题的两分钱:
我之前的消息格式如下:
{
"notification": {
"title": "AppName",
"sound": null,
"body": "Hey!YouhaveaMessage"
},
"data": {
"param1": null,
"param2": [
238
],
"id": 1
},
"to": "--the device push token here--"
}
我将消息格式修改为以下内容:
{
"data": {
"title": "AppName",
"body": "Hey! You have a message",
"param1": null,
"param2": [
238
],
"id": 1
},
"priority": "high",
"to": " — device push token here — "
}
然后,我从“数据”有效负载本身中检索了标题、正文和所有参数。这解决了问题,即使应用程序在后台,我也可以获得 OnMessageReceived 回调。 我写了一篇博文来解释同样的问题,你可以在这里找到它。
评论
“
"
我可能很晚才回答,但官方文档有点令人困惑。
此外,还明确指出有两种类型的通知
- 通知消息:FCM 自动处理
- 数据消息:由客户端应用处理。
毫无疑问,如果服务器发送数据消息,那么 onMessageReceived() 方法肯定会被调用,但在通知消息的情况下,onMessageReceived() 方法只有在应用程序处于前台时才会被调用,并且当应用程序在后台时,我们发送的数据只是空。
例:
假设服务器正在发送通知消息类型:
一个。在前景的情况下:
- remoteMessage.data[“key”] 将起作用
湾。如果是背景: -remoteMessage.data[“key”] 将返回 null 但在这里,如果您使用 getIntent().getExtras().getString(“key”) 在 defaul 活动中找到相同的意图数据将起作用
三.在杀戮的情况下: -remoteMessage.data[“key”] 将返回 null 但在这里,如果您使用 getIntent().getExtras().getString(“key”) 在 defaul 活动中找到相同的意图数据将起作用
现在,让我们假设服务器正在发送数据消息类型:
D.在前景的情况下:
- remoteMessage.data[“key”] 将起作用
E.如果是背景:
- remoteMessage.data[“key”] 将起作用
六.在杀戮的情况下:
- remoteMessage.data[“key”] 将起作用
毫无疑问,数据消息将始终调用 onMessageReceived() 方法,但如果通知消息并且应用程序处于后台/kill 状态,您可以使用 B 的解决方案。谢谢
我希望它能节省每个人的时间。
评论
{
"notification": {
"title": "Notification Title",
"body": "Notification Body",
"click_action": "ActivityToOpen"
},
"data": {
"key": "value "
},
"to": "id"
}
如果 FCM 有效负载具有如上所述的 notification{} 块,并且应用处于后台,系统会使用 notification{} 中给出的标题和正文为您构建通知。当用户单击它时,click_action中提到的活动将打开,如果未提供任何内容,则默认启动器活动将打开,并且可以从以下位置访问 data{} 块中的数据
intent.extras // of the launcher activity
如果应用位于前台,则会触发 FirebaseMessagingService() 类中的函数 onMessageReceived()。我们必须自己构建通知,我们可以按如下方式访问数据:
val value = message.data.getOrDefault("key", "")
如果 FCM 有效负载没有通知块{},如下所示;
{
"data": {
"title": "Notification Title",
"body": "Notification Body",
"key": "value "
},
"to" : "id"
}
FirebaseMessagingService() 类中的函数 onMessageReceived() 无论应用在后台还是前台都会被触发,我们必须自己构建通知。
我们可以按如下方式访问数据:
override fun onMessageReceived(message: RemoteMessage) {
super.onMessageReceived(message)
val title = message.data.getOrDefault("title", "")
val body = message.data.getOrDefault("body", "")
}
这是预期的行为,您需要在 firebase 通知数据集中设置click_action,以便能够从后台接收数据。
在此处查看更新的答案:https://stackoverflow.com/a/73724040/7904082
我认为告诉您将消息类型更改为数据的答案对您来说很清楚。
但有时,如果您无法确定您是收到的消息类型,则必须处理它。我在这里发布我的方法。您刚刚实现了 FirebaseMessagingService,并在 handlIntent() 方法中处理了您的消息。从那里,您可以自定义自己的通知。您可以实现自己的方法 sendYourNotificatoin()
class FCMPushService : FirebaseMessagingService() {
companion object {
private val TAG = "FCMPush"
}
override fun handleIntent(intent: Intent?) {
Logger.t(TAG).i("handleIntent:${intent.toString()}")
val data = intent?.extras as Bundle
val remoteMessage = RemoteMessage(data)
if (remoteMessage.data.isNotEmpty()) {
val groupId: String = remoteMessage.data[MESSAGE_KEY_GROUP_ID] ?: ""
val title = remoteMessage.notification?.title ?: ""
val body = remoteMessage.notification?.body ?: ""
if (title.isNotEmpty() && body.isNotEmpty())
sendYourNotificatoin(this, title, body, groupId)
}
}
}
评论
FirebaseMessagingService 具有
public void handleIntent(Intent intent) {
String action = intent.getAction();
if (!"com.google.android.c2dm.intent.RECEIVE".equals(action) && !"com.google.firebase.messaging.RECEIVE_DIRECT_BOOT".equals(action)) {
if ("com.google.firebase.messaging.NEW_TOKEN".equals(action)) {
this.onNewToken(intent.getStringExtra("token"));
} else {
Log.d("FirebaseMessaging", "Unknown intent action: " + intent.getAction());
}
} else {
this.handleMessageIntent(intent);
}
}
您可以简单地在自己的服务类中覆盖此函数,该类扩展了 FirebaseMessagingService。
this.handleMessageIntent(意图);-> 在应用程序关闭/后台时处理通知。您可以删除此行并使用覆盖的 onMessageRecieved() 方法中使用的函数来显示自定义布局。因此,您可以在背景/前景中显示自己的自定义布局。
评论