这是我的舱单:

<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]

当前回答

在一般情况下

FCM (Firebase Cloud Messaging)中有两种类型的消息:

显示消息:这些消息仅在应用程序处于前台时触发onmessagerreceived()回调 数据消息:这些消息触发onmessagerreceived()回调,即使你的应用程序在前台/后台/被杀死

数据电文示例:

{ 
  "to": "/path", 
  "data": 
     { 
      "my_custom_key": "my_custom_value", 
      "my_custom_key2": true 
     } 
}

显示消息示例:

 {
     "notification": {
            "title" : "title",
            "body"  : "body text",
            "icon"  : "ic_notification",
            "click_action" : "OPEN_ACTIVITY_1"
        }
   }

Android端可以处理如下通知:

public class MyFirebaseMessagingService extends FirebaseMessagingService {
    …

      @Override public void onMessageReceived(RemoteMessage remoteMessage){
           Map<String, String> data = remoteMessage.getData();
           String myCustomKey = data.get("my_custom_key");
        
       } 

    …

}

更多关于FCM的详细信息可以在这里找到:在Android上设置一个Firebase云消息客户端应用程序

其他回答

根据firebase文档在发送下游使用firebase,有两种类型的有效载荷:

数据 此参数指定消息有效负载的自定义键-值对。 客户端应用程序负责处理数据消息。数据消息只有自定义键值对。 通知 此参数指定通知有效负载的预定义的、用户可见的键-值对。FCM自动代表客户端应用程序将消息显示给最终用户设备。通知消息具有一组预定义的用户可见键。

当你在前台时,你可以使用onmessagerecreceived()在FCM内部获取数据,你可以从数据有效载荷中获取数据。

data = remoteMessage.getData();
String customData = (String) data.get("customData");

当您在后台时,FCM将根据通知有效载荷的信息在系统托盘中显示通知。系统托盘上用于通知的标题、消息和图标都来自通知有效负载。

{
  "notification": {
        "title" : "title",
        "body"  : "body text",
        "icon"  : "ic_notification",
        "click_action" : "OPEN_ACTIVITY_1"
       }
}

当你想在应用程序处于后台时自动在系统托盘上显示通知时,使用这个通知有效载荷。 当你的应用程序在后台运行时,为了获得通知数据,你应该在通知有效载荷中添加click_action。

如果你想打开你的应用并执行一个特定的动作(在后台),在通知有效载荷中设置click_action,并将其映射到你想要启动的Activity中的意图过滤器。例如,将click_action设置为OPEN_ACTIVITY_1来触发一个意图过滤器,如下所示:

<intent-filter>
  <action android:name="OPEN_ACTIVITY_1" />
  <category android:name="android.intent.category.DEFAULT" />
</intent-filter>

把intent-filter放在你的清单上,在你的一个activity标签里面。当你点击通知时,它将打开应用程序并直接进入你在click_action中定义的活动,在本例中为“OPEN_ACTIVTY_1”。 在这个活动中,你可以通过以下方式获取数据:

Bundle b = getIntent().getExtras();
String someData = b.getString("someData");

我使用FCM为我的android应用程序和使用两个有效载荷。 下面是我使用的JSON示例:

{
  "to": "FCM registration ID",
  "notification": {
    "title" : "title",
    "body"  : "body text",
    "icon"  : "ic_notification",
    "click_action" : "OPEN_ACTIVITY_1"
   },
   "data": {
     "someData"  : "This is some data",
     "someData2" : "etc"
   }
}

下面是关于firebase消息的更清晰的概念。我从他们的支援组找到的。

Firebase有三种消息类型:

通知消息:通知消息工作在后台或前台。当app在后台时,通知消息被传递到系统托盘。如果应用程序在前台,消息由onmessagerreceived()或didReceiveRemoteNotification回调处理。这些实质上就是所谓的显示消息。

数据消息:在Android平台上,数据消息可以工作在后台和前台。数据消息将由onMessageReceived()处理。在Android上,数据有效载荷可以在用于启动你的活动的Intent中检索。具体来说,如果你有"click_action":"launch_Activity_1",你只能通过getIntent()从Activity_1中检索这个意图。

Messages with both notification and data payloads: When in the background, apps receive the notification payload in the notification tray, and only handle the data payload when the user taps on the notification. When in the foreground, your app receives a message object with both payloads available. Secondly, the click_action parameter is often used in notification payload and not in data payload. If used inside data payload, this parameter would be treated as custom key-value pair and therefore you would need to implement custom logic for it to work as intended.

另外,我建议您使用onMessageReceived方法(参见数据消息)来提取数据包。根据您的逻辑,我检查了bundle对象,并没有发现预期的数据内容。这里有一个类似案例的参考,可能会更清楚。

欲了解更多信息,请访问我的这个线程

我也有同样的问题。经过一些挖掘为什么我的MainActivity被调用意图没有数据,我意识到我的发射器活动(如在Manifest)是SplashActivity。在那里我找到了消息数据,并将它们转发给MainActivity。效果很好。我相信这能帮助到一些人。

谢谢你的回答。

感谢你们所有人的回答。但是我通过发送数据消息而不是发送通知来解决这个问题。 服务器代码

<?php
$url = "https://fcm.googleapis.com/fcm/send";
$token = "C-l6T_a7HouUK****";
$serverKey = "AAAAaOcKS00:********";
define( 'API_ACCESS_KEY', $serverKey );
$registrationIds = array($token);
// prep the bundle

$msg = array

(
 'message'  => 'here is a message. message',
 'title'        => 'This is a title. title',
 'subtitle' => 'This is a subtitle. subtitle',
 'tickerText'   => 'Ticker text here...Ticker text here...Ticker text 
 here',
 'vibrate'  => 1,
 'sound'        => 1,
 'largeIcon'    => 'large_icon',
 'smallIcon'    => 'small_icon'

);

$fields = array

(
  'registration_ids'    => $registrationIds,
  'data'            => $msg

);
$headers = array

(
  'Authorization: key=' . API_ACCESS_KEY,
 'Content-Type: application/json'

);


$ch = curl_init();

curl_setopt( $ch,CURLOPT_URL, 'https://android.googleapis.com/gcm/send' 
);

curl_setopt( $ch,CURLOPT_POST, true );

curl_setopt( $ch,CURLOPT_HTTPHEADER, $headers );

curl_setopt( $ch,CURLOPT_RETURNTRANSFER, true );

curl_setopt( $ch,CURLOPT_SSL_VERIFYPEER, false );

curl_setopt( $ch,CURLOPT_POSTFIELDS, json_encode( $fields ) );

$result = curl_exec($ch );

curl_close( $ch );

echo $result;

?>

并在onmessagerreceived中捕获数据

public class MyFirebaseMessagingService extends FirebaseMessagingService     {

  private static final String TAG = "MyFirebaseMsgService";

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    Log.d(TAG, "From: " + remoteMessage.getFrom());

    // Check if message contains a data payload.
    if (remoteMessage.getData().size() > 0) {
        Log.d(TAG, "Message data payload: " + remoteMessage.getData());

      sendNotification(remoteMessage.getData().get("message"));
     }
   // Check if message contains a notification payload.
    else if (remoteMessage.getNotification() != null) {
        Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
    sendNotification(remoteMessage.getNotification().getBody());
    }


}
   private void sendNotification(String messageBody) {
    Intent intent = new Intent(this, Notify.class).putExtra("msg",messageBody);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
            PendingIntent.FLAG_ONE_SHOT);

    String channelId = "idddd";
    Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
    NotificationCompat.Builder notificationBuilder =
            new NotificationCompat.Builder(MyFirebaseMessagingService.this)
                    .setSmallIcon(R.mipmap.ic_launcher)
                    .setContentTitle("FCM Message")
                    .setContentText(messageBody)
                    .setAutoCancel(true)
                    .setSound(defaultSoundUri)
                    .setContentIntent(pendingIntent);

    NotificationManager notificationManager =
            (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

    notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
}

我觉得所有的响应都是不完整的,但它们都有一些你需要处理的东西,当你的应用程序在后台时,一个有数据的通知。

遵循这些步骤,你将能够在应用程序处于后台时处理通知。

添加一个intent-filter,像这样: <活动android: name = "。MainActivity”> <意图过滤器> <行动android: name = "。MainActivity " / > <category android:name="android.intent.category. default " /> < /意图过滤器>

到要处理通知数据的活动。

以以下格式发送通知: { “通知”:{ "click_action": "。MainActivity”, "body": "new Symulti update !", "title": "新的Symulti更新!", "icon": "ic_notif_symulti"}, "data":{…}, "to": "c9Vaa3ReGdk:APA91bH-AuXgg3lDN2WMcBrNhJZoFtYF9"}

这里的关键是加法

"click_action" : ".MainActivity"

其中. mainactivity是您在步骤1中添加的带有intent-filter的活动。

从.MainActivity的onCreate中的通知中获取数据信息: onCreate(Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); //获取通知数据信息 Bundle Bundle = getIntent().getExtras(); If (bundle != null) { //bundle必须包含通知的"data"字段发送的所有信息 } }

这就是你需要做的。