我正在使用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);
}
}
我也有类似的问题。根据本页中提到的答案和参考资料,以下是我如何用以下方法解决问题的两点意见:
我之前的消息格式如下:
{
"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 — "
}
然后我从“data”负载本身检索标题、主体和所有参数。这解决了问题,然后我可以得到onmessagerreceived回调,即使应用程序是在后台。
我写了一篇博客文章解释了同样的问题,你可以在这里找到。
{
"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", "")
}
我现在回答这个问题可能有点晚了,但是官方文件有点混乱。
它还明确指出,有两种类型的通知
通知消息:由FCM自动处理
数据消息:由客户端应用程序处理。
毫无疑问,如果服务器发送了一个数据消息,那么onmessagerecreceived()方法肯定会被调用,但在通知消息的情况下,onmessagerecreceived()方法只会在应用程序在前台被调用,当应用程序在后台时,我们发送的数据只是null。
例子:
假设服务器正在发送通知消息类型:
A.对于前景:
remoteMessage。Data ["key"]可以工作
B.背景情况:
-remoteMessage。Data ["key"]将返回null
但在这里,如果你在默认活动中发现相同的意图数据,getIntent().getExtras().getString("key")将工作
C.如发生灭杀:
-remoteMessage。Data ["key"]将返回null
但在这里,如果你在默认活动中发现相同的意图数据,getIntent().getExtras().getString("key")将工作
现在,让我们假设服务器正在发送数据消息类型:
D.前景情况:
remoteMessage。Data ["key"]可以工作
E.背景情况:
remoteMessage。Data ["key"]可以工作
F.如果杀死:
remoteMessage。Data ["key"]可以工作
毫无疑问,数据消息将始终调用onmessagerreceived()方法,但在通知消息和应用程序处于后台/kill状态的情况下,您可以使用b的解决方案
我希望这会节省大家的时间。