我正在使用Firebase并测试在后台运行时从服务器向我的应用发送通知。通知已成功发送,甚至出现在设备的通知中心,但是当出现通知或即使我单击通知时,也不会调用FCMessagingService中的onMessageReceived方法。

当我在前台运行应用程序时进行测试时,调用了onMessageReceived方法,并且一切正常。该应用程序在后台运行时会发生问题。

这是预期的行为,还是我可以解决此问题的方法?

这是我的FBMessagingService:

import android.util.Log;

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

public class FBMessagingService extends FirebaseMessagingService {

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        Log.i("PVL", "MESSAGE RECEIVED!!");
        if (remoteMessage.getNotification().getBody() != null) {
            Log.i("PVL", "RECEIVED MESSAGE: " + remoteMessage.getNotification().getBody());
        } else {
            Log.i("PVL", "RECEIVED MESSAGE: " + remoteMessage.getData().get("message"));
        }
    }
}


评论

除了json主体之外,您的onTokenRefresh代码在哪里?您完成了Android设置吗?

通知的json主体是什么意思?另外,我的onTokenRefresh代码位于FirebaseInstanceID服务内部。

您可以张贴要发送的有效负载样本吗?

使用istudy.io/android-push-notifications-using-firebase-fcm

您还可以检查此线程stackoverflow.com/questions/39046270/…

#1 楼

这可以按预期工作,仅当您的应用程序位于前台时,通知消息才会传递到onMessageReceived回调。如果您的应用处于后台或关闭状态,则通知中心中会显示一条通知消息,并且该消息中的任何数据都会传递到由于用户点击通知而启动的意图。

您可以指定click_action来指示用户点击通知时应启动的意图。如果未指定click_action,则使用main活动。

启动意图时,可以使用

getIntent().getExtras();


检索一个Set将包含与通知消息一起发送的所有数据。

有关通知消息的更多信息,请参阅docs。

评论


使用Firebase通知控制台时,是否可以设置click_action?

– Nii Laryea
16年5月31日在1:28

好的,但是如果应用程序被杀死(没有前台或后台)怎么办?

– michalu
16年6月15日在12:15

但是如何禁用用户丢弃通知?因为如果用户丢弃它,则意味着将跳过所有数据...对吗?

– Aleksey Timoshchenko
16年9月1日在15:33

正确!因此,在向Android发送通知消息时,随附的数据应为可增强通知体验的数据。它不应该是应用程序关键数据,即使用户关闭通知,也应使用数据消息获取应用程序所需的数据。

–亚瑟·汤普森(Arthur Thompson)
16年9月2日在22:49

这并不完全正确。如果消息仅包含数据而不是通知有效负载,则无论应用程序是否处于前台,消息都将始终传递到onMessageReceive。

–JacksOnF1re
17年8月15日在8:42

#2 楼

从服务器请求中完全删除notification字段。仅发送data并在onMessageReceived()中进行处理,否则当应用程序在后台或被杀死时,不会触发您的onMessageReceived()

不要忘记在通知请求中包含"priority": "high"字段。根据文档:数据消息以正常优先级发送,因此它们不会立即到达;这也可能是问题。

这是我从服务器发送的内容

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


所以您可以像这样在onMessageReceived(RemoteMessage message)中接收数据。必须获取ID

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


评论


我发现如果仅发送数据消息,则从任务管理器中清除的App无法获得通知。这是否是预期的行为?

–普拉哈特·辛格(Prabhjot Singh)
16 Dec 28'在6:26

这是我在后台接收消息的解决方案!

– Ray Hulha
17年1月10日在15:01

在奥利奥(Oreo)中,当应用程序被杀死时,不会调用onMessageReceived。我只是有数据的有效载荷。你有什么更新吗?

– Samir Mangroliya
18-2-27在12:47

奇迹般有效!

–sk
18年6月30日在1:27

爱你很多这个答案:p

–艾哈迈德·阿尔斯兰(Ahmad Arslan)
18年8月30日在12:07

#3 楼

此方法handleIntent()已被弃用,因此可以按以下方式处理通知:


前景状态:单击通知将转到您提供的待处理Intent的活动。同时以编程方式创建通知(通常使用通知的数据有效负载创建)。
背景/杀死状态-在此,系统本身会基于通知有效负载创建通知,然后单击该通知会将您带到启动器应用程序的活动,您可以在其中使用任何生命周期方法轻松获取Intent数据。


评论


谢谢!!!我在这个问题上失去了几天,而这个救了我。

–伊戈尔·扬科维奇(IgorJanković)
17年5月24日在9:42

确实是完美的解决方案!

–EduXavier
17年5月24日在13:20

我正在handleIntent(Intent intent)中处理通知显示逻辑,但是当应用程序在后台运行时,将显示2条通知,其中一条是我创建的,另一条是默认情况下包含通知中的整个消息的。

–乔森
17年9月9日在15:33

太棒了,但是在这种情况下,我看不到OnMessageReceived有任何用处!

– Alaa AbuZarifa
17-10-4在11:12

我正在使用com.google.firebase:firebase-messaging:11.6.2&handleIntent现在是最终版本。请检查stackoverflow.com/questions/47308155/…

–Ronak Poriya
17年12月18日在7:12

#4 楼

这是有关Firebase消息的更清晰的概念。我是从他们的支持团队那里找到的。

Firebase具有三种消息类型:

通知消息:通知消息可在后台或前台使用。当应用程序在后台运行时,通知消息将传递到系统托盘。如果应用位于前台,则消息由onMessageReceived()didReceiveRemoteNotification回调处理。这些基本上就是所谓的显示消息。

数据消息:在Android平台上,数据消息可以在后台和前台运行。数据消息将由onMessageReceived()处理。这里有一个特定于平台的注释:在Android上,可以在用于启动活动的Intent中检索数据有效负载。详细地说,如果您有"click_action":"launch_Activity_1",则可以仅从getIntent()通过Activity_1检索此意图。

同时具有通知和数据有效负载的消息:在后台时,应用程序会在通知托盘中接收通知有效负载,并且仅在用户点击通知时处理数据有效负载。在前台时,您的应用程序会收到一个同时具有两个有效负载的消息对象。其次,click_action参数通常用于通知有效负载中,而不用于数据有效负载中。如果在数据有效载荷内部使用,则此参数将被视为自定义键值对,因此您需要实现自定义逻辑以使其按预期工作。

此外,我建议您使用onMessageReceived方法(请参阅数据消息)以提取数据束。根据您的逻辑,我检查了bundle对象,但未找到预期的数据内容。这是对类似情况的引用,它可能会更加清楚。

从服务器端,firebase通知应采用以下格式:

服务器端应发送“ notification”对象。我的TargetActivity中缺少“通知”对象,但没有使用getIntent()接收消息。

下面给出了正确的消息格式:

{
 "data": {
  "body": "here is body",
  "title": "Title"
 },
"notification": {
  "body": "here is body",
  "title": "Title",
  "click_action": "YOUR_ACTION"
 },
 "to": "ffEseX6vwcM:APA91bF8m7wOF MY FCM ID 07j1aPUb"
}


以下是有关Firebase消息的更清晰的概念。我是从他们的支持团队那里找到的。

有关更多信息,请访问我的这个线程和这个线程

评论


值得一提的是,如果设备处于深度打ze模式(Android 7.0中引入),则不会收到“数据消息”。小心那些!

– Sameer J
19年2月21日在21:03

#5 楼

我有同样的问题。使用“数据消息”而不是“通知”会更容易。数据消息始终加载onMessageReceived类。在该类中,您可以使用notificationbuilder发出自己的通知。

示例:

 @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        sendNotification(remoteMessage.getData().get("title"),remoteMessage.getData().get("body"));
    }

    private void sendNotification(String messageTitle,String messageBody) {
        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this,0 /* request code */, intent,PendingIntent.FLAG_UPDATE_CURRENT);

        long[] pattern = {500,500,500,500,500};

        Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

        NotificationCompat.Builder notificationBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.ic_stat_name)
                .setContentTitle(messageTitle)
                .setContentText(messageBody)
                .setAutoCancel(true)
                .setVibrate(pattern)
                .setLights(Color.BLUE,1,1)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);

        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
    }


评论


谢谢..我更改了服务器代码,并使用“数据”而不是“通知”,现在它可以正常工作了,

–马赫什·卡瓦蒂亚(Mahesh Kavathiya)
16 Jun 2'在5:40



@Koot仅当应用程序在前台时才起作用,而在后台时则不起作用。您能在两种情况下帮助我触发此事件吗?

– Anant Shah
16年7月16日在6:09

@AnantShah您到Firebase服务器的POST看起来如何?

– Koot
16年7月23日在10:01

实际上,这里有三种可能的情况。 1)应用程序在前台。 2)后台应用程序。 3)应用未运行。如您所说,当应用程序未运行时,在前两种情况下会收到“数据”消息,而在第三种情况下不会。为了满足这三种情况,您需要在消息中设置“ notification”字段。 (如果您想同时支持iOS和Android客户端,也是一个好主意)

–史蒂夫·莫斯利(Steve Moseley)
16年8月26日在2:29

即使在应用程序未运行的情况下,我仍然会从onmessagereceived函数上的服务器获取消息。我同意您的看法,如果您也想支持ios,最好使用“通知”。

– Koot
16年8月27日在7:20

#6 楼

根据Firebase Cloud Messaging文档-如果Activity位于前台,则将调用onMessageReceived。如果“活动”处于后台或关闭状态,则通知中心中会显示有关应用启动器活动的通知消息。
如果您的应用程序处于后台,则可以通过单击通知来调用自定义活动,方法是调用rest服务api作为Firebase消息传递, :

URL-https://fcm.googleapis.com/fcm/send

方法类型-POST

Header- Content-Type:application/json
Authorization:key=your api key


身体/有效载荷:

{ "notification": {
    "title": "Your Title",
    "text": "Your Text",
     "click_action": "OPEN_ACTIVITY_1" // should match to your intent filter
  },
    "data": {
    "keyname": "any value " //you can get this data as extras in your activity and this data is optional
    },
  "to" : "to_id(firebase refreshedToken)"
} 


在您的应用程序中,您可以在活动中添加以下代码,称为:

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


评论


我在哪里创建意图并使其打开特定活动?我知道这在清单中注册了OPEN_ACTIVITY_1意图,但是我实际在哪里调用呢?

– Cyogenos
16年6月3日在16:22

检查以下内容:firebase.google.com/docs/cloud-messaging/…

– Ankit Adlakha
16年6月6日在16:16

我们应该从意图过滤器中调用活动吗?还是在onMessageReceived中手动启动它?

– CoolMind
19年6月25日在8:05

#7 楼

基于以下情况调用onMessageReceived(RemoteMessage remoteMessage)方法。



FCM响应带有通知和数据块:

{
  
"to": "device token list",
  "notification": {
    "body": "Body of Your Notification",
    "title": "Title of Your Notification"
  },
  "data": {
    "body": "Body of Your Notification in Data",
    "title": "Title of Your Notification in Title",
    "key_1": "Value for key_1",
    "image_url": "www.abc.com/xyz.jpeg",
    "key_2": "Value for key_2"
  }
}



前景中的应用程序:

onMessageReceived(RemoteMessage remoteMessage)被调用,在通知栏中显示LargeIcon和BigPicture。我们可以在后台的通知和数据块中读取内容。


应用程序在后台:

onMessageReceived(RemoteMessage remoteMessage)未调用,系统托盘将接收到消息并从通知栏读取正文和标题,并在通知栏中显示默认消息和标题。



FCM响应仅包含数据块:

在这种情况下,从json中删除通知块

{
  
"to": "device token list",
  "data": {
    "body": "Body of Your Notification in Data",
    "title": "Title of Your Notification in Title",
    "key_1": "Value for key_1",
    "image_url": "www.abc.com/xyz.jpeg",
    "key_2": "Value for key_2"
  }
}


在前台中调用onMessageReceived()的解决方案


应用程序的调用方法:

onMessageReceived(RemoteMessage remoteMessage)被调用,在其中显示LargeIcon和BigPicture通知栏。我们可以从后台的通知和数据块中读取内容。


应用程序在后台:

onMessageReceived(RemoteMessage remoteMessage)被调用,系统托盘将不会收到消息,因为通知键中的不在响应中。在通知栏中显示LargeIcon和BigPicture

代码

 private void sendNotification(Bitmap bitmap,  String title, String 
    message, PendingIntent resultPendingIntent) {

    NotificationCompat.BigPictureStyle style = new NotificationCompat.BigPictureStyle();
    style.bigPicture(bitmap);

    Uri defaultSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

    NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
    String NOTIFICATION_CHANNEL_ID = mContext.getString(R.string.default_notification_channel_id);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "channel_name", NotificationManager.IMPORTANCE_HIGH);

        notificationManager.createNotificationChannel(notificationChannel);
    }
    Bitmap iconLarge = BitmapFactory.decodeResource(mContext.getResources(),
            R.drawable.mdmlogo);
    NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(mContext, NOTIFICATION_CHANNEL_ID)
            .setSmallIcon(R.drawable.mdmlogo)
            .setContentTitle(title)
            .setAutoCancel(true)
            .setSound(defaultSound)
            .setContentText(message)
            .setContentIntent(resultPendingIntent)
            .setStyle(style)
            .setLargeIcon(iconLarge)
            .setWhen(System.currentTimeMillis())
            .setPriority(Notification.PRIORITY_MAX)
            .setChannelId(NOTIFICATION_CHANNEL_ID);


    notificationManager.notify(1, notificationBuilder.build());


}


参考链接:

https:// firebase .google.com / docs / cloud-messaging / android / receive

评论


对于遭受后台问题的人们来说,最重要的部分是从服务器发送的JSON中删除“ notification”属性。这解决了问题。非常感谢。

–拉米·穆萨(Ramy M. Mousa)
4月21日21:46

#8 楼

如果应用程序处于后台模式或处于非活动状态(被杀死),然后单击“通知”,则应在LaunchScreen中检查有效负载(在我的情况下,启动屏幕为MainActivity.java)。

因此在MainActivity中.java ononCreate检查其他功能:

    if (getIntent().getExtras() != null) {
        for (String key : getIntent().getExtras().keySet()) {
            Object value = getIntent().getExtras().get(key);
            Log.d("MainActivity: ", "Key: " + key + " Value: " + value);
        }
    }


评论


如何获得通知标题,正文和数据?

–塔里库尔伊斯兰教医生
18年1月2日在9:38

谢谢,这就是答案。 @ Md.Tarikul Islam使用onMessageReceived()来解决此问题。

– felixwcf
18年1月26日在6:42

#9 楼

我有同样的问题。如果应用程序为前台-会触发我的后台服务,因此我可以根据通知类型更新数据库。
但是,应用程序进入后台-默认通知服务会注意将通知显示给服务器。用户。

这是我的解决方案,用于在后台识别应用程序并触发您的后台服务,

public class FirebaseBackgroundService extends WakefulBroadcastReceiver {

  private static final String TAG = "FirebaseService";

  @Override
  public void onReceive(Context context, Intent intent) {
    Log.d(TAG, "I'm in!!!");

    if (intent.getExtras() != null) {
      for (String key : intent.getExtras().keySet()) {
        Object value = intent.getExtras().get(key);
        Log.e("FirebaseDataReceiver", "Key: " + key + " Value: " + value);
        if(key.equalsIgnoreCase("gcm.notification.body") && value != null) {
          Bundle bundle = new Bundle();
          Intent backgroundIntent = new Intent(context, BackgroundSyncJobService.class);
          bundle.putString("push_message", value + "");
          backgroundIntent.putExtras(bundle);
          context.startService(backgroundIntent);
        }
      }
    }
  }
}


在manifest.xml中

<receiver android:exported="true" android:name=".FirebaseBackgroundService" android:permission="com.google.android.c2dm.permission.SEND">
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            </intent-filter>
        </receiver>


在最新的android 8.0版本中测试了此解决方案。谢谢

评论


为什么要使用此FirebaseBackgroundService类? @Nagendra Badiganti

–user1731387
17年11月22日在6:48

在何处使用此代码公共类FirebaseBackgroundService扩展了WakefulBroadcastReceiver @Nagendra Badiganti

–user1731387
17年11月22日在7:17

在您的包中创建一个服务类,并在manifest.xml中注册。确保您具有通知过滤器。由于服务会为每个GCM通知触发。

– Nagendra Badiganti
17年11月22日在7:30



firebase.google.com/docs/cloud-messaging/android/…我正在关注此链接,我需要添加此类以接收通知。只是从firebase的第一条消息发送消息..它说完成了,但是没有收到通知@Nagendra Badiganti

–user1731387
17年11月22日在9:09

从API级别26.1.0开始不推荐使用WakefulBroadcastReceiver。

– Minoru
18年2月22日在15:50

#10 楼

覆盖handleIntentFirebaseMessageService方法适用于我。

这里是C#(Xamarin)中的代码

public override void HandleIntent(Intent intent)
{
    try
    {
        if (intent.Extras != null)
        {
            var builder = new RemoteMessage.Builder("MyFirebaseMessagingService");

            foreach (string key in intent.Extras.KeySet())
            {
                builder.AddData(key, intent.Extras.Get(key).ToString());
            }

            this.OnMessageReceived(builder.Build());
        }
        else
        {
            base.HandleIntent(intent);
        }
    }
    catch (Exception)
    {
        base.HandleIntent(intent);
    }
}


,这就是Java中的代码

public void handleIntent(Intent intent)
{
    try
    {
        if (intent.getExtras() != null)
        {
            RemoteMessage.Builder builder = new RemoteMessage.Builder("MyFirebaseMessagingService");

            for (String key : intent.getExtras().keySet())
            {
                builder.addData(key, intent.getExtras().get(key).toString());
            }

            onMessageReceived(builder.build());
        }
        else
        {
            super.handleIntent(intent);
        }
    }
    catch (Exception e)
    {
        super.handleIntent(intent);
    }
}


评论


handleIntent()是最终的

–埃托尔
17年11月16日在9:57

@Ettore如何调用handleIntent函数?

–广藤
17年11月16日在16:03

从Firebase收到消息时将调用该方法,但是由于该方法被声明为final,因此无法覆盖该方法。 (Firebase 11.6.0)

–埃托尔
17年11月16日在17:04

#11 楼

默认情况下,当您的应用程序在后台运行并单击通知时,将启动您应用程序中的启动器活动,如果您的通知中包含任何数据部分,则可以按以下相同的活动进行处理,

if(getIntent().getExtras()! = null){
  //do your stuff
}else{
  //do that you normally do
}


评论


如果我从mainActivity导航,如何导航回特定的Activity?

– Mac_Play
18 Mar 11 '18 at 14:16

@Uzair getIntent()。getExtras()总是为空,您还有其他解决方案吗?当应用程序免费运行时,onMessageReceived方法未调用

– Komal12
19 Mar 28 '19在3:41

#12 楼

如果应用默认情况下在后台Fire-base中处理通知,但是如果我们要自定义通知,则必须更改服务器端,该服务器端负责发送自定义数据(数据有效负载)

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

现在,您的服务器端代码格式如下所示:

{
  "collapse_key": "CHAT_MESSAGE_CONTACT",
  "data": {
    "loc_key": "CHAT_MESSAGE_CONTACT",
    "loc_args": ["John Doe", "Contact Exchange"],
    "text": "John Doe shared a contact in the group Contact Exchange",
    "custom": {
      "chat_id": 241233,
      "msg_id": 123
    },
    "badge": 1,
    "sound": "sound1.mp3",
    "mute": true
  }
}


注意:请参见上面的代码中的这一行
“ text”:“ John Doe在“联系人交换”组中共享了一个联系人”
在数据有效载荷中,您应该使用“ text “”参数代替“ body”或“ message”参数来进行消息描述或任何您要使用的文本。

onMessageReceived()

@Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        Log.e(TAG, "From: " + remoteMessage.getData().toString());

        if (remoteMessage == null)
            return;

        // Check if message contains a data payload.
        if (remoteMessage.getData().size() > 0) {
           /* Log.e(TAG, "Data Payload: " + remoteMessage.getData().toString());*/
            Log.e(TAG, "Data Payload: " + remoteMessage);

            try {

                Map<String, String> params = remoteMessage.getData();
                JSONObject json = new JSONObject(params);
                Log.e("JSON_OBJECT", json.toString());


                Log.e(TAG, "onMessageReceived: " + json.toString());

                handleDataMessage(json);
            } catch (Exception e) {
                Log.e(TAG, "Exception: " + e.getMessage());
            }
        }
    }


#13 楼

只需在MainActivity的onCreate方法中调用此方法即可:

if (getIntent().getExtras() != null) {
           // Call your NotificationActivity here..
            Intent intent = new Intent(MainActivity.this, NotificationActivity.class);
            startActivity(intent);
        }


评论


如果我从mainActivity导航,如何导航回特定的Activity?

– Mac_Play
18年3月11日在14:15

#14 楼

根据t3h Exi的解决方案,我想在这里发布干净的代码。只需将其放入MyFirebaseMessagingService中即可,如果应用程序处于后台模式,则一切正常。您至少需要编译com.google.firebase:firebase-messaging:10.2.1

 @Override
public void handleIntent(Intent intent)
{
    try
    {
        if (intent.getExtras() != null)
        {
            RemoteMessage.Builder builder = new RemoteMessage.Builder("MyFirebaseMessagingService");

            for (String key : intent.getExtras().keySet())
            {
                builder.addData(key, intent.getExtras().get(key).toString());
            }



           onMessageReceived(builder.build());
        }
        else
        {
            super.handleIntent(intent);
        }
    }
    catch (Exception e)
    {
        super.handleIntent(intent);
    }
}


评论


我正在尝试实现您的解决方案,但是handleIntent()方法在我的SDK版本(SDK 27)中是最终的,因此无法在服务中覆盖它...

–matdev
18年1月15日在11:17

是的,但这不是我的错或给予-1的任何理由!很嚣张。直到Firebase 11.4.2生效,然后google对其进行更改(将此方法定为最终版本)。因此,现在您必须使用通知对自己的解决方案进行编程。

–坦白
18年1月18日在20:09

我没有给-1但给了+1!

–matdev
18年1月18日在21:57

你救了我的工作:P

–amitabha2715
18年2月26日在8:09

#15 楼

我遇到了这个问题(如果应用程序在后台或关闭,则应用程序不想在单击通知时打开),问题是通知正文中的click_action无效,请尝试将其删除或更改为有效的内容。

#16 楼

值得强调的一点是,即使应用程序在后台,您也必须使用数据消息-仅数据密钥-来调用onMessageReceived处理程序。您的有效负载中不应包含任何其他通知消息键,否则,如果应用程序在后台运行,则处理程序将不会被触发。

此处已提及(但未在FCM文档中强调) :

https://firebase.google.com/docs/cloud-messaging/concept-options#notifications_and_data_messages


使用您的应用服务器和FCM服务器API :仅设置数据密钥。可以
可折叠或不可折叠。


#17 楼

我正在使用的后端正在使用通知消息,而不是数据消息。因此,在阅读完所有答案后,我尝试从启动的活动的意图包中检索额外内容。
但是无论我尝试从getIntent().getExtras();检索哪个键,该值始终为null。

但是,我终于找到了一种使用Notification消息发送数据并从意图中检索数据的方法。

此处的关键是将数据有效负载添加到Notification消息中。

示例:

{
    "data": {
        "message": "message_body",
        "title": "message_title"
    },
    "notification": {
        "body": "test body",
        "title": "test title"
    },
    "to": "E4An.."
}


完成此操作后,您将可以通过以下方式获取信息:

intent.getExtras().getString("title")
将是message_title


intent.getExtras().getString("message")
将是message_body

参考

#18 楼

如果您的问题与显示大图像有关,即您正在从Firebase控制台发送带有图像的推送通知,并且仅当应用程序在前台时才显示图像。解决此问题的方法是发送仅包含数据字段的推送消息。像这样的东西:

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


评论


您在“ AnotherActivity”之前输了逗号。我的android震动了,但实际上什么也没显示(没有文字,没有图像,没有推送)。

– Jekaby
17年6月22日在9:41

#19 楼

试试这个:

public void handleIntent(Intent intent) {
    try {
        if (intent.getExtras() != null) {
            RemoteMessage.Builder builder = new RemoteMessage.Builder("MyFirebaseMessagingService");
            for (String key : intent.getExtras().keySet()) {
            builder.addData(key, intent.getExtras().get(key).toString());
        }
            onMessageReceived(builder.build());
        } else {
            super.handleIntent(intent);
        }
    } catch (Exception e) {
        super.handleIntent(intent);
    }
}


评论


在Firebase:11.8.0及更高版本中不再使用handleIntent。

– Shihab Uddin
18年4月8日在13:36

#20 楼

当收到消息且您的应用程序处于后台时,通知将发送到主要活动的额外意图。

您可以在主要活动的oncreate()或onresume()函数中检查额外的值活动。

您可以检查数据,表等字段(通知中指定的字段)

例如我使用数据作为键发送的

public void onResume(){
    super.onResume();
    if (getIntent().getStringExtra("data")!=null){
            fromnotification=true;
            Intent i = new Intent(MainActivity.this, Activity2.class);
            i.putExtra("notification","notification");
            startActivity(i);
        }

}


#21 楼

我遇到了同样的问题,对此进行了更多的研究。当应用程序在后台运行时,会向系统任务栏发送一条通知消息,但会将数据消息发送至onMessageReceived()
请参阅https://firebase.google.com/docs/cloud-messaging/downstream#monitor -token-generation_3
和https://github.com/firebase/quickstart-android/blob/master/messaging/app/src/main/java/com/google/firebase/quickstart/fcm/MyFirebaseMessagingService.java

为确保您发送的消息,文档说:“使用您的应用服务器和FCM服务器API:仅设置数据密钥。可折叠或不可折叠。”
请参阅https://firebase.google.com/docs/cloud-messaging/concept-options#notifications_and_data_messages

#22 楼

消息有两种类型:通知消息和数据消息。
如果仅发送数据消息,则消息字符串中没有通知对象。当您的应用程序在后台运行时会被调用。

#23 楼

检查@Mahesh Kavathiya的答案。就我而言,在服务器代码中只有这样:

{
"notification": {
  "body": "here is body",
  "title": "Title",
 },
 "to": "sdfjsdfonsdofoiewj9230idsjkfmnkdsfm"
}


您需要更改为:

{
 "data": {
  "body": "here is body",
  "title": "Title",
  "click_action": "YOUR_ACTION"
 },
"notification": {
  "body": "here is body",
  "title": "Title"
 },
 "to": "sdfjsdfonsdofoiewj9230idsjkfmnkdsfm"
}


然后,如果应用程序在后台运行,则默认的活动意图额外将获得“数据”。

祝你好运!

#24 楼

您可以在后台的主活动中尝试此操作
   if (getIntent().getExtras() != null) {
            for (String key : getIntent().getExtras().keySet()) {
                Object value = getIntent().getExtras().get(key);
                Log.d(TAG, "Key: " + key + " Value: " + value);
            }
        }

检查以下项目作为参考

#25 楼

只需重写FirebaseMessagingService的OnCreate方法即可。当您的应用程序在后台运行时被调用:

public override void OnCreate()
{
    // your code
    base.OnCreate();
}


评论


如果您可以添加说明并链接到一些文档,则此答案可能会更有用。您能告诉我们这对您有什么帮助吗?

– kilokahn
18年7月2日在19:19

@kilokahn你能告诉我你不明白什么吗?必须将所指示的方法插入问题的代码中,并完全回答问题。该代码适用于Xamarin,但您可以简单地在java中进行转换。

– Renzo Ciot
18年7月4日在15:50

AFAIK官方文档(firebase.google.com/docs/cloud-messaging/android/client)并未讨论在扩展FirebaseMessagingService的服务中覆盖OnCreate的问题-如果您可以访问扩展文档,也许可以共享一个链接?另外,从您的答案中,还不清楚重写onCreate如何解决单击通知时无法调用onMessageReceived的问题-因此需要更多信息。

– kilokahn
18年7月5日,0:31



该文档没有提及OnCreate方法的替代,但是它可以工作,因为我在生产中使用了它。您想在onMessageReceived方法中插入的代码,显然可以用来执行一些后台操作的代码,可以在OnCreate上执行。

– Renzo Ciot
18年7月5日在6:46



在这种情况下,详细说明它对您有用的事实可能比列出解决方案更有用。同样,未记录的行为很可能会随意停止使用更新,并且使用更新的人必须准备在更新时重新编写代码。此免责声明需要加入。

– kilokahn
18年7月5日在19:52

#26 楼

Firebase推送通知有2种类型:

1-通知消息(显示消息)->
-1.1如果选择此变体,则操作系统会自行创建通知应用程序在后台运行,并将在intent中传递数据。

-1.2如果应用程序位于前景中,则将通过callback-function中的FirebaseMessagingService接收通知,由客户端来处理。

2-数据消息(最多4k数据)->这些消息用于仅向客户端发送数据(无提示),并且由客户端处理两种情况下的背景/前景数据FirebaseMessagingService中的回调函数

这是根据官方文档:https://firebase.google.com/docs/cloud-messaging/concept-options