这是我的舱单:

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

当前回答

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]

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

其他回答

根据文件

Handle messages in a backgrounded app When your app is in the background, Android directs notification messages to the system tray. A user tap on the notification opens the app launcher by default. This includes messages that contain both notification and data payload. In these cases, the notification is delivered to the device's system tray, and the data payload is delivered in the extras of the intent of your launcher Activity. If you want to open your app and perform a specific action, set click_action in the notification payload and map it to an intent filter in the Activity you want to launch. For example, set click_action to OPEN_ACTIVITY_1 to trigger an intent filter like the following:

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

编辑:

基于这个线程:

不能使用Firebase Console设置click_action有效负载。您可以尝试使用curl命令或自定义http服务器进行测试

curl --header "Authorization: key=<YOUR_KEY_GOES_HERE>" 
     --header Content-Type:"application/json" https://fcm.googleapis.com/fcm/send  
     -d "{\"to\":\"/topics/news\",\"notification\": 
         {\"title\": \"Click Action Message\",\"text\": \"Sample message\",
            \"click_action\":\"OPEN_ACTIVITY_1\"}}"

截至2019年7月

Android compileSdkVersion 28, buildToolsVersion 28.0.3和firebase-messaging:19.0.1

经过许多小时的研究,通过所有其他StackOverflow问题和答案,并尝试无数过时的解决方案,这个解决方案设法在以下3个场景中显示通知:

—应用程序在前台: 通知是由我的MyFirebaseMessagingService类的onmessagerreceived方法接收的

应用程序已经被杀死(它不在后台运行) FCM自动将通知发送到通知托盘。当用户触摸通知时,应用程序通过调用manifest中有android.intent.category.LAUNCHER的活动来启动。你可以在onCreate()方法中使用getIntent(). getextras()来获取通知的数据部分。

- App is in background: the notification is sent to the notification tray automatically by FCM. When the user touches the notification the app is brought to the foreground by launching the activity that has android.intent.category.LAUNCHER in the manifest. As my app has launchMode="singleTop" in that activity, the onCreate() method is not called because one activity of the same class is already created, instead the onNewIntent() method of that class is called and you get the data part of the notification there by using intent.getExtras().

步骤: 1-如果你这样定义你的应用程序的主活动:

<activity
    android:name=".MainActivity"
    android:label="@string/app_name"
    android:largeHeap="true"
    android:screenOrientation="portrait"
    android:launchMode="singleTop">
    <intent-filter>
        <action android:name=".MainActivity" />
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

2-在MainActivity.class的onCreate()方法中添加这些行

Intent i = getIntent();
Bundle extras = i.getExtras();
if (extras != null) {
    for (String key : extras.keySet()) {
        Object value = extras.get(key);
        Log.d(Application.APPTAG, "Extras received at onCreate:  Key: " + key + " Value: " + value);
    }
    String title = extras.getString("title");
    String message = extras.getString("body");
    if (message!=null && message.length()>0) {
        getIntent().removeExtra("body");
        showNotificationInADialog(title, message);
    }
}

和这些方法到同一个MainActivity.class:

@Override
public void onNewIntent(Intent intent){
    //called when a new intent for this class is created.
    // The main case is when the app was in background, a notification arrives to the tray, and the user touches the notification

    super.onNewIntent(intent);

    Log.d(Application.APPTAG, "onNewIntent - starting");
    Bundle extras = intent.getExtras();
    if (extras != null) {
        for (String key : extras.keySet()) {
            Object value = extras.get(key);
            Log.d(Application.APPTAG, "Extras received at onNewIntent:  Key: " + key + " Value: " + value);
        }
        String title = extras.getString("title");
        String message = extras.getString("body");
        if (message!=null && message.length()>0) {
            getIntent().removeExtra("body");
            showNotificationInADialog(title, message);
        }
    }
}


private void showNotificationInADialog(String title, String message) {

    // show a dialog with the provided title and message
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setTitle(title);
    builder.setMessage(message);
    builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
            dialog.cancel();
        }
    });
    AlertDialog alert = builder.create();
    alert.show();
}

3-像这样创建MyFirebase类:

package com.yourcompany.app;

import android.content.Intent;
import android.util.Log;

import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;

public class MyFirebaseMessagingService extends FirebaseMessagingService {


    public MyFirebaseMessagingService() {
        super();
    }

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {

        Log.d(Application.APPTAG, "myFirebaseMessagingService - onMessageReceived - message: " + remoteMessage);

        Intent dialogIntent = new Intent(this, NotificationActivity.class);
        dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        dialogIntent.putExtra("msg", remoteMessage);
        startActivity(dialogIntent);

    }

}

4-创建一个新类NotificationActivity.class,如下所示:

package com.yourcompany.app;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.view.ContextThemeWrapper;

import com.google.firebase.messaging.RemoteMessage;

public class NotificationActivity extends AppCompatActivity {

private Activity context;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    context = this;
    Bundle extras = getIntent().getExtras();

    Log.d(Application.APPTAG, "NotificationActivity - onCreate - extras: " + extras);

    if (extras == null) {
        context.finish();
        return;
    }

    RemoteMessage msg = (RemoteMessage) extras.get("msg");

    if (msg == null) {
        context.finish();
        return;
    }

    RemoteMessage.Notification notification = msg.getNotification();

    if (notification == null) {
        context.finish();
        return;
    }

    String dialogMessage;
    try {
        dialogMessage = notification.getBody();
    } catch (Exception e){
        context.finish();
        return;
    }
    String dialogTitle = notification.getTitle();
    if (dialogTitle == null || dialogTitle.length() == 0) {
        dialogTitle = "";
    }

    AlertDialog.Builder builder = new AlertDialog.Builder(new ContextThemeWrapper(context, R.style.myDialog));
    builder.setTitle(dialogTitle);
    builder.setMessage(dialogMessage);
    builder.setPositiveButton(getResources().getString(R.string.accept), new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
            dialog.cancel();
        }
    });
    AlertDialog alert = builder.create();
    alert.show();

}

}

5-添加这些行到你的应用程序清单,在你的标签

    <service
        android:name=".MyFirebaseMessagingService"
        android:exported="false">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>

    <meta-data android:name="com.google.firebase.messaging.default_notification_channel_id" android:value="@string/default_notification_channel_id"/>

    <activity android:name=".NotificationActivity"
        android:theme="@style/myDialog"> </activity>

    <meta-data
        android:name="com.google.firebase.messaging.default_notification_icon"
        android:resource="@drawable/notification_icon"/>

    <meta-data
        android:name="com.google.firebase.messaging.default_notification_color"
        android:resource="@color/color_accent" />

6-在Application.java的onCreate()方法或MainActivity.class的onCreate()方法中添加这些行:

      // notifications channel creation
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
      // Create channel to show notifications.
      String channelId = getResources().getString("default_channel_id");
      String channelName = getResources().getString("General announcements");
      NotificationManager notificationManager = getSystemService(NotificationManager.class);
      notificationManager.createNotificationChannel(new NotificationChannel(channelId,
              channelName, NotificationManager.IMPORTANCE_LOW));
  }

完成了。

现在,为了在上述3个场景中很好地工作,你必须以以下方式从Firebase web控制台发送通知:

In the Notification section: Notification Title = Title to display in the notification dialog (optional) Notification text = Message to show to the user (required) Then in the Target section: App = your Android app and in Additional Options section: Android Notification Channel = default_channel_id Custom Data key: title value: (same text here than in the Title field of the Notification section) key: body value: (same text here than in the Message field of the Notification section) key:click_action value: .MainActivity Sound=Disabled Expires=4 weeks

你可以在模拟器中调试它与API 28谷歌播放。

编码快乐!

像这样简单的总结

如果你的应用正在运行; onMessageReceived ()

是触发器。

如果你的应用程序没有运行(通过滑动杀死); onMessageReceived ()

不是直接触发和传递的。如果你有特殊的键值对。它们不工作,因为onmessagerecreceived()不工作。

我找到了这条路;

在你的启动器活动中,放入这样的逻辑,

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState, R.layout.activity_splash);

    if (getIntent().getExtras() != null && getIntent().getExtras().containsKey("PACKAGE_NAME")) {

        // do what you want

        // and this for killing app if we dont want to start
        android.os.Process.killProcess(android.os.Process.myPid());

    } else {

        //continue to app
    }
}

在这个if块中,根据firebase UI搜索你的密钥。

在这个例子中,我的键和值就像上面那样;(对不起,语言=))

当我的代码工作时,我得到“com.rda.note”。

android.os.Process.killProcess(android.os.Process.myPid());

有了这行代码,我关闭了我的应用程序,打开谷歌播放市场

快乐编码=)

下面是关于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。效果很好。我相信这能帮助到一些人。

谢谢你的回答。