我正在使用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"));
        }
    }
}

当前回答

这是预期的工作,通知消息只有当你的应用程序在前台时才被传递到你的onmessagerreceived回调。如果你的应用程序在后台或关闭,那么通知中心会显示一条通知消息,来自该消息的任何数据都会传递给意图,而用户点击通知的结果就是启动该消息。

您可以在JSON中指定click_action,以指示当用户点击通知时应该启动的意图。如果没有指定click_action,则使用主活动。

当意图启动时,你可以使用

getIntent().getExtras();

检索包含随通知消息一起发送的任何数据的Set。

有关通知消息的更多信息,请参阅文档。

其他回答

如果你的问题与显示大图有关,例如,如果你从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" }

根据Firebase云消息文档-如果Activity在前台,那么onmessagerecreceived将被调用。如果Activity处于后台或关闭,则通知消息将显示在应用程序启动器活动的通知中心。 你可以调用你的自定义活动点击通知,如果你的应用程序是在后台调用rest服务api为firebase消息:

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>

这是预期的行为,您需要在firebase通知数据集中设置click_action,以便能够从后台接收数据。

请看这里更新的答案: https://stackoverflow.com/a/73724040/7904082

根据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);
    }
}

如果应用程序在后台Fire-base默认处理通知,但如果我们想要我们的自定义通知,那么我们必须改变我们的服务器端,它负责发送我们的自定义数据(数据有效载荷)

从服务器请求中完全删除通知有效负载。只发送数据并在onmessagerecreceived()中处理它,否则当应用程序在后台或被杀死时,你的onmessagerecreceived将不会被触发。

现在,你的服务器端代码格式是这样的,

{
  "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在群组联系人交换中共享了一个联系人" 在数据有效载荷中,你应该使用“文本”参数而不是“正文”或“消息”参数来描述消息或任何你想使用文本的内容。

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());
            }
        }
    }