这是我的舱单:

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

当前回答

为了能够从应用程序在后台发送的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
            //
        }
    }

其他回答

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {

}

不是每次调用它时,只有当应用程序是在前景

有一个覆盖方法,这个方法每次都会被调用,不管什么应用程序在前台,在后台或被杀死,但是这个方法在这个firebase API版本中可用

这是你必须从gradle导入的版本

compile 'com.google.firebase:firebase-messaging:10.2.1'

这就是方法

@Override
public void handleIntent(Intent intent) {
    super.handleIntent(intent);

    // you can get ur data here 
    //intent.getExtras().get("your_data_key") 


}

在之前的firebase API中,这个方法是不存在的 当应用程序在后台....时,Fire base句柄本身现在你有了这个方法 无论你想做什么…你可以在这里用这个方法.....

如果您使用的是以前的版本,那么默认活动将启动 在这种情况下,你可以用同样的方法得到数据

if(getIntent().getExtras() != null && getIntent().getExtras().get("your_data_key") != null) {
String strNotificaiton = getIntent().getExtras().get("your_data_key").toString();

//做你想做的事.... }

通常这是我们在通知中从服务器获得的结构

{
    "notification": {
        "body": "Cool offers. Get them before expiring!",
        "title": "Flat 80% discount",
        "icon": "appicon",
        "click_action": "activity name" //optional if required.....
    },
    "data": {
        "product_id": 11,
        "product_details": "details.....",
        "other_info": "......."
    }
}

这是由你决定的,你想给数据键或者你想给任何你可以给.......的通知 无论你在这里给出什么,用相同的键,你都会得到数据.........

有少数情况下,如果你没有发送点击动作在这种情况下,当你将点击通知默认活动将打开,但如果你想打开你的特定活动时,应用程序是在后台,你可以从这个handleIntent方法调用你的活动,因为这是每次调用

此情况仅用于firebase管理通知 如果应用程序在后台,则不会触发FirebaseMessagingService

要处理这种情况,请转到launcher activity,检查附加的intent bundle,并使用以下代码打印出所有数据:

 intent?.extras?.let {it->
        for (key in bundle.keySet()) {
            val value = bundle[key]
            Log.d("NotificationData", String.format("%s %s (%s)", key, value.toString(), value!!.javaClass.name))
        }
    }

显示所有数据类型的签入日志;

例子:

我想从通知中获得周和标题将使用这段代码

intent?.extras?.let {it->
        if (it.containsKey("week")){
            
        }
        if (it.containsKey("title")){

        }

下面是关于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对象,并没有发现预期的数据内容。这里有一个类似案例的参考,可能会更清楚。

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

根据OAUTH 2.0:

由于FCM现在使用OAUTH 2,在这种情况下将会有认证问题

所以我阅读了firebase文档,并根据文档发布数据消息的新方法是;

POST: https://fcm.googleapis.com/v1/projects/YOUR_FIREBASEDB_ID/messages:send

Key: Content-Type, Value: application/json

Auth

Bearer YOUR_TOKEN 

例子的身体

{
   "message":{
    "topic" : "xxx",
    "data" : {
         "body" : "This is a Firebase Cloud Messaging Topic Message!",
         "title" : "FCM Message"
          }
      }
 }

在url中有数据库Id,你可以在你的firebase控制台上找到它。(Go项目设置)

现在让我们用我们的代币(它只有效1小时):

首先在Firebase控制台中,打开设置>服务帐户。单击“生成新的私钥”,安全存储包含该私钥的JSON文件。我需要这个JSON文件来手动授权服务器请求。我下载了。

然后我创建了一个node.js项目,并使用这个函数来获得我的令牌;

var PROJECT_ID = 'YOUR_PROJECT_ID';
var HOST = 'fcm.googleapis.com';
var PATH = '/v1/projects/' + PROJECT_ID + '/messages:send';
var MESSAGING_SCOPE = 'https://www.googleapis.com/auth/firebase.messaging';
var SCOPES = [MESSAGING_SCOPE];

  router.get('/', function(req, res, next) {
      res.render('index', { title: 'Express' });
      getAccessToken().then(function(accessToken) {
        console.log("TOKEN: "+accessToken)
      })

    });

function getAccessToken() {
return new Promise(function(resolve, reject) {
    var key = require('./YOUR_DOWNLOADED_JSON_FILE.json');
    var jwtClient = new google.auth.JWT(
        key.client_email,
        null,
        key.private_key,
        SCOPES,
        null
    );
    jwtClient.authorize(function(err, tokens) {
        if (err) {
            reject(err);
            return;
        }
        resolve(tokens.access_token);
    });
});
}

现在我可以在我的post请求中使用这个令牌。然后我发布我的数据消息,它现在由我的应用程序onmessagerecreceived函数处理。

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

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

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