我正在使用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"));
}
}
}
我也有同样的问题。如果应用程序是前台-它会触发我的后台服务,我可以根据通知类型更新我的数据库。
但是,应用程序将转到后台-默认的通知服务将小心地向用户显示通知。
下面是我在后台识别应用程序并触发后台服务的解决方案,
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);
}
}
}
}
}
在manifest.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版本中测试了该解决方案。谢谢
我现在回答这个问题可能有点晚了,但是官方文件有点混乱。
它还明确指出,有两种类型的通知
通知消息:由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的解决方案
我希望这会节省大家的时间。
我认为告诉您将消息类型更改为数据的答案对您来说很清楚。
但有时,如果你不能决定你收到的消息类型,你必须处理它。我把我的方法贴在这里。您刚刚实现了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)
}
}
}