这是我的舱单:

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

当前回答

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

这是我从服务器发送的:

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

你可以像这样在onMessageReceived(RemoteMessage message)中接收你的数据(假设我需要获取id)

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

类似地,你可以在onmessagerecreceived()内从服务器获得任何数据。

其他回答

1. 为什么会这样?

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

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

注意:Firebase团队还没有开发用于发送数据消息的UI 还有你的设备。您应该使用您的服务器发送这种类型!



2. 如何?

为了实现这一点,你必须对以下URL执行POST请求:

文章https://fcm.googleapis.com/fcm/send

关键字:Content-Type,值:application/json Key: Authorization, Value: Key =<your-server-key>

主体使用主题

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

或者如果你想把它发送到特定的设备

{
    "data": {
        "my_custom_key": "my_custom_value",
        "my_custom_key2": true
     },
    "registration_ids": ["{device-token}","{device2-token}","{device3-token}"]
}

注意:请确保您没有添加JSON键通知 注意:要获得服务器密钥,您可以在firebase控制台中找到它:您的项目->设置->项目设置->云消息传递->服务器密钥

3.如何处理推送通知消息?

这是你如何处理收到的消息:

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

     // Manage data
}

根据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"
   }
}

发送消息的简单方法,即使应用程序是在后台和前台如下:- 要使用API发送消息,您可以使用一个名为AdvancedREST客户端工具,它是一个chrome扩展,并发送带有以下参数的消息。

Rest客户端工具链接:https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofddffdnphfgcellkdfbfbjeloo

使用这个url:- https://fcm.googleapis.com/fcm/send 内容类型:application / json 授权:key=您的服务器密钥或授权密钥(参见下面的参考)

{ "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"
}

授权密钥可以通过访问谷歌开发人员控制台,并单击项目左侧菜单上的凭证按钮来获得。在列出的API密钥中,服务器密钥将是您的授权密钥。

并且您需要将接收者的tokenID放在使用API发送的POST请求的“to”部分。

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.

为了能够从应用程序在后台发送的firebase通知中检索数据,您需要在通知数据集中添加click_action条目。

在firebase控制台设置额外的通知选项,如下所示:(你必须包括你想在应用程序中检索的任何额外数据):

并包括意图过滤器在你的manifest文件下的活动要启动

    <activity
            android:name=".MainActivity"
            android:exported="true"
            android:label="@string/app_name"
            android:theme="@style/Theme.MyApp.SplashScreen">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            <intent-filter>
                <action android:name="FIREBASE_NOTIFICATION_CLICK" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
    </activity>

然后在你的onNewIntent活动中获取bundle数据:

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        Bundle data = intent.getExtras();
        if (data != null) {
            for (String key : data.keySet()) {
                Object value = data.get(key);
                // do what you want with the data entries
                Log.d(FIREBASE_TAG, "Key: " + key + " Value: " + value);
                Toast.makeText(this, "Key: "+key+"....  Value: "+value, Toast.LENGTH_LONG).show;
            }
        }
    }

当你的应用程序在前台时,你可以像这样设置onmessagerecreceived:

@Override
    public void onMessageReceived(@NonNull RemoteMessage message) {
        Log.d(FIREBASE_TAG, "Message From: " + message.getFrom());

        if (message.getNotification() != null) {
            Intent intent = new Intent(this, MainActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            Map<String, String> data = message.getData();
            if(data != null && !data.isEmpty()){
                for(Map.Entry<String ,String > entry : data.entrySet()) {
                    intent.putExtra(entry.getKey(), entry.getValue());
                }
            }
            //.......
            // implement the rest of the code to show notification
            //
        }
    }