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

当前回答

如果应用程序在后台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());
            }
        }
    }

其他回答

我认为告诉您将消息类型更改为数据的答案对您来说很清楚。

但有时,如果你不能决定你收到的消息类型,你必须处理它。我把我的方法贴在这里。您刚刚实现了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)
    }
}

}

我有这个问题(应用程序不想打开通知点击,如果应用程序是在后台或关闭),问题是在通知主体无效的click_action,尝试删除或更改为有效的东西。

我也有同样的问题。如果应用程序是前台-它会触发我的后台服务,我可以根据通知类型更新我的数据库。 但是,应用程序将转到后台-默认的通知服务将小心地向用户显示通知。

下面是我在后台识别应用程序并触发后台服务的解决方案,

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版本中测试了该解决方案。谢谢

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

不要忘记在你的通知请求中包含“priority”:“high”字段。根据文档:数据消息以正常优先级发送,因此它们不会立即到达;这也可能是问题所在。

这是我从服务器发送的

{
  "data":{
    "id": 1,
    "missedRequests": 5
    "addAnyDataHere": 123
  },
  "to": "fhiT7evmZk8:APA91bFJq7Tkly4BtLRXdYvqHno2vHCRkzpJT8QZy0TlIGs......",
  "priority": "high"
}

所以你可以在onMessageReceived(RemoteMessage message)中接收你的数据,就像这个....假设我需要得到id

Object obj = message.getData().get("id");
        if (obj != null) {
            int id = Integer.valueOf(obj.toString());
        }

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

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