我正在使用Firebase并测试在应用程序处于后台时从服务器发送通知到我的应用程序。通知发送成功,它甚至出现在设备的通知中心,但当通知出现或即使我点击它,我的FCMessagingService中的onmessagerreceived方法永远不会被调用。
当我测试这个,而我的应用程序是在前台,onmessagerreceived方法被调用,一切工作正常。问题发生在应用程序在后台运行时。
这是我有意为之的行为吗,或者我有办法解决这个问题吗?
这是我的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"));
}
}
}
重写FirebaseMessageService的handleIntent方法对我有用。
下面是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);
}
}
下面是关于firebase消息的更清晰的概念。我从他们的支援组找到的。
Firebase有三种消息类型:
通知消息:通知消息工作在后台或前台。当app在后台时,通知消息被传递到系统托盘。如果应用程序在前台,消息由onmessagerreceived()或didReceiveRemoteNotification回调处理。这些实质上就是所谓的显示消息。
数据消息:在Android平台上,数据消息可以工作在后台和前台。数据消息将由onMessageReceived()处理。在Android上,数据有效载荷可以在用于启动你的活动的Intent中检索。具体来说,如果你有"click_action":"launch_Activity_1",你只能通过getIntent()从Activity_1中检索这个意图。
Messages with both notification and data payloads: When in the background, apps receive the notification payload in the notification tray, and only handle the data payload when the user taps on the notification. When in the foreground, your app receives a message object with both payloads available. Secondly, the click_action parameter is often used in notification payload and not in data payload. If used inside data payload, this parameter would be treated as custom key-value pair and therefore you would need to implement custom logic for it to work as intended.
另外,我建议您使用onMessageReceived方法(参见数据消息)来提取数据包。根据您的逻辑,我检查了bundle对象,并没有发现预期的数据内容。这里有一个类似案例的参考,可能会更清楚。
从服务器端,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"
}
下面是关于firebase消息的更清晰的概念。我从他们的支援组找到的。
欲了解更多信息,请访问我的这个线程和这个线程
{
"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"
}
函数onmessagerecreceived()在FirebaseMessagingService()类被触发,无论应用程序是在后台或前台,我们将不得不建立自己的通知。
我们可以通过以下方式访问数据:
override fun onMessageReceived(message: RemoteMessage) {
super.onMessageReceived(message)
val title = message.data.getOrDefault("title", "")
val body = message.data.getOrDefault("body", "")
}