这是我的舱单:

<service android:name=".fcm.PshycoFirebaseMessagingServices">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

<service android:name=".fcm.PshycoFirebaseInstanceIDService">
    <intent-filter>
        <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
    </intent-filter>
</service>

当应用程序在后台和通知到达,然后默认通知来,不运行我的onmessagerreceived代码。

这是我的onMessageReceived代码。如果我的应用程序在前台运行,而不是在后台运行,就会调用这个函数。我怎么能运行这段代码时,应用程序是在后台太?

// [START receive_message]
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    // TODO(developer): Handle FCM messages here.
    // If the application is in the foreground handle both data and notification messages here.
    // Also if you intend on generating your own notifications as a result of a received FCM
    // message, here is where that should be initiated. See sendNotification method below.
    data = remoteMessage.getData();
    String title = remoteMessage.getNotification().getTitle();
    String message = remoteMessage.getNotification().getBody();
    String imageUrl = (String) data.get("image");
    String action = (String) data.get("action");
    Log.i(TAG, "onMessageReceived: title : "+title);
    Log.i(TAG, "onMessageReceived: message : "+message);
    Log.i(TAG, "onMessageReceived: imageUrl : "+imageUrl);
    Log.i(TAG, "onMessageReceived: action : "+action);

    if (imageUrl == null) {
        sendNotification(title,message,action);
    } else {
        new BigPictureNotification(this,title,message,imageUrl,action);
    }
}
// [END receive_message]

当前回答

我想出了各种方案

当app在前台时, onMessageReceived()方法从FirebaseService调用。因此,服务类中定义的pendingIntent将被调用。

当app在后台时,第一个activity被调用。

现在,如果你使用了一个splashactivity,那么必须记住splashactivity会被调用,否则如果没有splashactivity,那么无论第一个activity是什么,都会被调用。

然后你需要检查firstActivity的getIntent(),看看它是否有任何bundle。如果一切正常,你会看到bundle在那里,值被填充。如果从服务器发送的数据标签中的值是这样的,

"data": {
    "user_name": "arefin sajib",
    "value": "user name notification"
  }

然后在第一个活动中,你会看到, 有一个有效的意图(getIntent()不是null),有效的捆绑包和在捆绑包内,会有上面提到的以数据为键的整个JSON。

在这种情况下,提取值的代码是这样的,

    if(getIntent()!=null){
            Bundle bundle = getIntent().getExtras();
            if (bundle != null) {
                try {
                   JSONObject object = new JSONObject(bundle.getStringExtra("data"));
String user_name = object.optString("user_name");

                } catch (JSONException e) {
                    e.printStackTrace();
                }


            }
        }

其他回答

2018年6月答案:

你必须确保消息中没有“通知”关键字。只包括“data”,应用程序将能够处理onmessagerreceived中的消息,即使在后台或已杀死。

使用云功能:

const message = {
    token: token_id,   // obtain device token id by querying data in firebase
    data: {
       title: "my_custom_title",
       body:  "my_custom_body_message"
       }
    }


return admin.messaging().send(message).then(response => {
    // handle response
});

然后在onmessagerreceived()中,在你的类中扩展com.google.firebase.messaging.FirebaseMessagingService:

if (data != null) {
  Log.d(TAG, "data title is: " + data.get("title");
  Log.d(TAG, "data body is: " + data.get("body");
}

// build notification using the body, title, and whatever else you want.

我想出了各种方案

当app在前台时, onMessageReceived()方法从FirebaseService调用。因此,服务类中定义的pendingIntent将被调用。

当app在后台时,第一个activity被调用。

现在,如果你使用了一个splashactivity,那么必须记住splashactivity会被调用,否则如果没有splashactivity,那么无论第一个activity是什么,都会被调用。

然后你需要检查firstActivity的getIntent(),看看它是否有任何bundle。如果一切正常,你会看到bundle在那里,值被填充。如果从服务器发送的数据标签中的值是这样的,

"data": {
    "user_name": "arefin sajib",
    "value": "user name notification"
  }

然后在第一个活动中,你会看到, 有一个有效的意图(getIntent()不是null),有效的捆绑包和在捆绑包内,会有上面提到的以数据为键的整个JSON。

在这种情况下,提取值的代码是这样的,

    if(getIntent()!=null){
            Bundle bundle = getIntent().getExtras();
            if (bundle != null) {
                try {
                   JSONObject object = new JSONObject(bundle.getStringExtra("data"));
String user_name = object.optString("user_name");

                } catch (JSONException e) {
                    e.printStackTrace();
                }


            }
        }

2023年1月 对于那些实现了最新的Firebase云消息(FCM)的应用程序,您可能不会被限制在后台或完全关闭的情况下分别为应用程序发送数据和通知以处理数据。正如这里的一些回答所解释的那样,简短的版本是:

在你的启动器活动上,监视启动时的额外内容; 测试您的FCM数据中的唯一键是否在列表中; 如果存在,获取必要的数据并调用您的活动来处理您想要做的处理。

//Firebase
// [START handle_data_extras]
if (getIntent().getExtras() != null) {
    boolean fcmExtraFlag = false;
    for (String key : getIntent().getExtras().keySet()) {
        Object value = getIntent().getExtras().get(key);
        Log.d(TAG, "Key: " + key + " Value: " + value);
        if(key.equalsIgnoreCase("tracerId")){
            //test your known key to be sure it is from fcm
            //this must have come from notification (system) tray
            //this will come whether the app was in the background or completely off
            //generally, this could be in the main activity as it has the intent-filter already set
            fcmExtraFlag = true;
        }
    }
    //pick fcm values if present and notify and/or process accordingly
    //you may add time-lookup to ignore delayed (time-passed) ones; and ignore
    if(fcmExtraFlag){
        String tracerId = (String) getIntent().getExtras().get("tracerId"); 
        //prepare your data as needed
        String tracerData = tracerId+">"+data-one+">"+data-two;
        String msgBody = "This is a test notification; data received: "+tracerId;
        String fcmMessage = msgBody;
        //start your confirmation activity, directly or whichever way
        SidUtils.firebaseStartConfirms(msgBody, tracerData, this);
    }
}
// [END handle_data_extras]

如前所述,如果可能的话,这应该在你的主活动中,以处理你的应用程序实际上关闭的情况-而不仅仅是在后台。这些将通过点击系统托盘上的应用程序通知来触发。

我通过使用广播消息解决了这个问题。

创建一个Broadcast并从service worker中以Broadcast Message的形式发送有效负载。

然后在应用程序中接收有效负载并按您想要的方式处理它。

你要工作onmessagerreceived (RemoteMessage RemoteMessage)在后台只发送数据部分通知部分这:

"data":    "image": "",    "message": "Firebase Push Message Using API", 

"AnotherActivity": "True", "to": "设备id或设备令牌"

通过这个onMessageRecivied是调用后台和前台不需要处理通知使用通知托盘在你的启动器活动。 处理数据负载使用这个:

  public void onMessageReceived(RemoteMessage remoteMessage)
    if (remoteMessage.getData().size() > 0) 
    Log.d(TAG, "Message data payload: " + remoteMessage.getData());