Firebase onMessageReceived не вызывается, когда приложение в фоновом режиме

Я работаю с Firebase и тестирую отправку уведомлений в мое приложение с моего сервера, пока приложение находится в фоновом режиме. Уведомление отправлено успешно, оно даже появляется в центре уведомлений устройства, но когда уведомление появляется или даже если я нажимаю на него, метод onMessageReceived внутри моего FCMessagingService никогда не вызывается.

Когда я проверял это, когда мое приложение находилось на переднем плане, был вызван метод 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"));
        }
    }
}

33 ответа

Решение

Это работает по назначению, уведомления отправляются на ваш обратный вызов onMessageReceived только тогда, когда ваше приложение находится на переднем плане. Если ваше приложение находится в фоновом режиме или закрыто, то в центре уведомлений отображается уведомление, и любые данные из этого сообщения передаются в намерение, которое запускается в результате нажатия пользователем уведомления.

Вы можете указать click_action, чтобы указать намерение, которое должно быть запущено, когда уведомление касается пользователя. Основное действие используется, если не указано click_action.

Когда намерение запущено, вы можете использовать

getIntent().getExtras();

чтобы получить набор, который будет включать любые данные, отправленные вместе с уведомлением.

Для получения дополнительной информации об уведомлении см. Документацию.

Удалить notification поле полностью из вашего запроса сервера. Отправлять только data и справиться с этим в onMessageReceived() в противном случае ваш onMessageReceived() не будет срабатывать, когда приложение находится в фоновом режиме или убито.

Не забудьте включить "priority": "high" поле в вашем запросе на уведомление. Согласно документации: сообщения данных отправляются с обычным приоритетом, поэтому они не будут поступать мгновенно; это также может быть проблемой.

Вот что я отправляю с сервера

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

Таким образом, вы можете получить свои данные в onMessageReceived(RemoteMessage message) как это.... скажем, я должен получить идентификатор

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

УСТАРЕЛИ РЕШЕНИЕ:

У меня есть идеальное решение для этого:

Вам нужно выполнить 2 простых шага:

  1. Обновите ваш FireBase до версии компиляции com.google.firebase:firebase-messaging:10.2.1
  2. Override handleIntent(Intent intent) метод в вашем FirebaseMessagingService учебный класс.

handleIntent() Метод вызывается каждый раз, когда приложение находится на переднем плане, в фоновом режиме или в состоянии завершения.

Вот более четкие понятия о сообщении Firebase. Я нашел это от их команды поддержки.

Firebase имеет три типа сообщений:

Уведомления: Уведомление работает на заднем или переднем плане. Когда приложение находится в фоновом режиме, уведомления уведомлений доставляются в системный трей. Если приложение находится на переднем плане, сообщения обрабатываются onMessageReceived() или же didReceiveRemoteNotification Обратные вызовы. По сути, это то, что называется отображением сообщений.

Сообщения данных: На платформе Android сообщение данных может работать как на заднем, так и на переднем плане. Сообщение данных будет обработано onMessageReceived(). Примечание для конкретной платформы будет следующим: На Android полезная нагрузка данных может быть получена в Intent, используемом для запуска вашей деятельности. Для уточнения, если у вас есть "click_action":"launch_Activity_1" Вы можете получить это намерение через getIntent() только из Activity_1,

Сообщения с полезными нагрузками как для уведомлений, так и для данных. В фоновом режиме приложения получают полезную нагрузку для уведомлений в области уведомлений и обрабатывают полезные данные только тогда, когда пользователь нажимает на уведомление. На переднем плане ваше приложение получает объект сообщения с обоими полезными нагрузками. Во-вторых, параметр click_action часто используется в полезных данных уведомлений, а не в полезных данных. Если этот параметр используется внутри полезных данных, этот параметр будет обрабатываться как настраиваемая пара ключ-значение, и поэтому вам нужно будет реализовать настраиваемую логику, чтобы он работал как задумано.

Также я рекомендую использовать метод onMessageReceived (см. Сообщение данных) для извлечения пакета данных. По вашей логике я проверил объект пакета и не нашел ожидаемого содержимого данных. Вот ссылка на похожий случай, который может дать больше ясности.

Для получения дополнительной информации посетите мою эту тему

У меня такая же проблема. Проще использовать "сообщение с данными" вместо "уведомления". Сообщение данных всегда загружает класс onMessageReceived.

В этом классе вы можете сделать свое собственное уведомление с помощью мастера уведомлений.

Пример:

 @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());
    }

В соответствии с документацией Firebase Cloud Messaging - если Activity находится на переднем плане, то вызывается onMessageReceived. Если действие находится в фоновом режиме или закрыто, то в центре уведомлений отображается уведомление об активности запуска приложения. Вы можете вызвать свою индивидуальную активность по щелчку уведомления, если ваше приложение находится в фоновом режиме, вызвав API службы отдыха для передачи сообщений в Firebase как:

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

Тип метода - POST

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

Тело /Payload:

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

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"
  }
}
  1. Приложение на переднем плане:

onMessageReceived(RemoteMessage remoteMessage), показывает LargeIcon и BigPicture на панели уведомлений. Мы можем читать контент как из уведомления, так и из блока данных

  1. Приложение в фоновом режиме:

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()

  1. Приложение на переднем плане:

onMessageReceived(RemoteMessage remoteMessage), показывает LargeIcon и BigPicture на панели уведомлений. Мы можем читать контент как из уведомления, так и из блока данных

  1. Приложение в фоновом режиме:

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

Если приложение находится в фоновом режиме или неактивно (убито), и вы нажимаете на Уведомление, вы должны проверить полезную нагрузку в LaunchScreen(в моем случае экран запуска - MainActivity.java).

Итак, в MainActivity.java onCreate проверьте наличие дополнений:

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

У меня та же проблема. Если приложение на переднем плане - оно запускает мою фоновую службу, где я могу обновить свою базу данных в зависимости от типа уведомления. Но приложение переходит в фоновый режим - служба уведомлений по умолчанию будет заботиться о том, чтобы показывать уведомление пользователю.

Вот мое решение для идентификации приложения в фоновом режиме и запуска вашего фонового сервиса,

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. Спасибо

Переопределить handleIntent Метод FirebaseMessageService работает для меня.

здесь код в 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);
    }
}

Я думаю, что ответы, говорящие вам об изменении типа сообщения на данные , вам понятны.

Но иногда, если вы не можете определить тип сообщения, которое вы получили, вам приходится с этим справляться. Выкладываю свой метод здесь. Вы только что реализовали FirebaseMessagingService и обработали свое сообщение в методе handlIntent() . Оттуда вы можете настроить свое собственное уведомление. Вы можете реализовать свой собственный метод sendYourNotificatoin ()

      class FCMPushService : FirebaseMessagingService() {

companion object {
    private val TAG = "FCMPush"
}



override fun handleIntent(intent: Intent?) {
    Logger.t(TAG).i("handleIntent:${intent.toString()}")
    val data = intent?.extras as Bundle
    val remoteMessage = RemoteMessage(data)

    if (remoteMessage.data.isNotEmpty()) {
        val groupId: String = remoteMessage.data[MESSAGE_KEY_GROUP_ID] ?: ""
        val title = remoteMessage.notification?.title ?: ""
        val body =  remoteMessage.notification?.body ?: ""
        if (title.isNotEmpty() && body.isNotEmpty())
            sendYourNotificatoin(this, title, body, groupId)
    }
}

}

Возможно, я очень опоздал с ответами, но официальная документация немного сбивает с толку.

Также четко указано, что существует два типа уведомлений.

  • Уведомление : автоматически обрабатывается FCM
  • Сообщение с данными : обрабатывается клиентским приложением.

Несомненно, если сервер отправляет сообщение данных, тогда методы onMessageReceived() определенно вызываются, но в случае сообщения уведомления метод onMessageReceived() будет вызываться только в том случае, если приложение находится на переднем плане, а когда приложение находится в фоновом режиме, данные мы отправляют просто null.

Пример:

Предположим, сервер отправляет уведомление типа сообщения:

A. В случае переднего плана:

  • remoteMessage.data ["ключ"] будет работать

B. В случае фона: -remoteMessage.data ["key"] вернет null, но здесь, если вы обнаружите те же данные о намерениях в действиях по умолчанию с getIntent(). GetExtras(). GetString("key") будет работать

C. В случае kill: -remoteMessage.data ["key"] вернет null, но здесь, если вы обнаружите те же данные о намерениях в действиях по умолчанию с getIntent(). GetExtras(). GetString("key") будет работать

Теперь предположим, что сервер отправляет сообщение с данными:

D. В случае переднего плана:

  • remoteMessage.data ["ключ"] будет работать

E. В случае предыстории:

  • remoteMessage.data ["ключ"] будет работать

F. В случае убийства:

  • remoteMessage.data ["ключ"] будет работать

Нет сообщений данных сомнения всегда вызывает onMessageReceived() метод , но в случае уведомления и сообщения приложения находится в состоянии фона / глушения вы можете использовать раствор B . Спасибо

Надеюсь, это сэкономит всем время.

По умолчанию активность Launcher в вашем приложении будет запущена, когда ваше приложение находится в фоновом режиме, и вы щелкаете уведомление, если у вас есть какая-либо часть данных с уведомлением, вы можете обрабатывать ее в том же действии, как показано ниже,

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

Я реализовал этот простой способ отправки сообщений, даже если приложение закрыто, в фоновом режиме и на переднем плане тоже. Я ранее использовал firebase консоль, но я получаю только сообщения, а не изображения и пользовательские данные.

Для отправки этих пользовательских данных с изображением вы можете использовать инструмент под названием AdvancedREST Client, это расширение chrome, и отправьте сообщение со следующими параметрами:

Rest client tool Link: https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofddffdnphfgcellkdfbfbjeloo

использовать этот url:- https://fcm.googleapis.com/fcm/send Content-Type:application/json Authorization:key=Your Server key From or Authorization 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" 
}

Ключ авторизации можно получить, посетив консоль разработчиков Google и нажав кнопку Credentials в левом меню вашего проекта. Среди перечисленных ключей API ключом авторизации будет ключ сервера.

И нужно поставить tokenID приемника в to раздел вашего POST Запрос отправлен с использованием API.

И этот кусок кода Android // сообщение будет содержать Push-сообщение

String message = remoteMessage.getData().get("message1");

//imageUri will contain URL of the image to be displayed with Notification
String imageUri = remoteMessage.getData().get("image");

//If the key AnotherActivity has  value as True then when the user taps on notification, in the app AnotherActivity will be opened.
//If the key AnotherActivity has  value as False then when the user taps on notification, in the app MainActivity2 will be opened.
String TrueOrFlase = remoteMessage.getData().get("AnotherActivity");

//To get a Bitmap image from the URL received
bitmap = getBitmapfromUrl(imageUri);

sendNotification(message, bitmap, TrueOrFlase);

В соответствии с решением от Ex3 t3h я хотел бы опубликовать чистый код здесь. Просто поместите его в 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);
    }
}

Попробуй это:

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);
    }
}

У меня была аналогичная проблема. Основываясь на ответах и ​​ссылках, упомянутых на этой странице, вот мои два цента за то, как я решил свою проблему с помощью следующего подхода:

Формат сообщения, который у меня был ранее, был следующим:

      {
“notification”: {
“title”: “AppName”,
“sound”: null,
“body”: “Hey! You have a Message”
},
“data”: {
“param1”: null,
“param2”: [
238
],
“id”: 1
},
“to”: “ — device push token here — ”
}

Я изменил формат сообщения на следующий:

      {
“data”: {
“title”: “AppName”,
“body”: “Hey! You have a message”
“param1”: null,
“param2”: [
238
],
“id”: 1
},
“priority”:”high”,
“to”: “ — device push token here — ”
}

Затем я извлек заголовок, тело и все параметры из самой полезной нагрузки «данных». Это решило проблему, и я смог получить обратный вызов OnMessageReceived, даже если приложение находится в фоновом режиме. Я написал сообщение в блоге, объясняющее ту же проблему, вы можете найти его здесь .

Если приложение находится в фоновом режиме. 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
  }
}

ПРИМЕЧАНИЕ: см. Эту строку в приведенном выше коде
"текст": "Джон Доу поделился контактом в группе" Обмен данными "" в разделе "Полезные данные". Вы должны использовать параметр "текст" вместо параметров "тело" или "сообщение" для описания сообщения или любого другого текста, который вы хотите использовать.

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());
            }
        }
    }
      {
      "notification": {
        "title": "Notification Title",
        "body": "Notification Body",
        "click_action": "ActivityToOpen"
      },
      "data": {
        "key": "value "
      },
      "to": "id"
}

Если полезная нагрузка FCM имеет блок уведомлений{}, подобный приведенному выше, и приложение работает в фоновом режиме, система создает для вас уведомление с заголовком и телом, указанными в уведомлении{}. Когда пользователь щелкает по нему, открывается действие, упомянутое в click_action, если ничего не указано, открывается действие средства запуска по умолчанию, и данные внутри блока данных {} могут быть доступны из

      intent.extras // of the launcher activity

Если приложение находится на переднем плане, срабатывает функция onMessageReceived() в классе FirebaseMessagingService(). Нам нужно будет создать уведомление самостоятельно, и мы можем получить доступ к данным следующим образом:

      val value = message.data.getOrDefault("key", "")

Если полезная нагрузка FCM не содержит блока уведомлений {}, как показано ниже;

      { 
    "data": {
    "title": "Notification Title",
     "body": "Notification Body",
    "key": "value "
    },
  "to" : "id"
} 

Функция onMessageReceived() в классе FirebaseMessagingService() запускается независимо от того, находится ли приложение в фоновом или переднем плане, и нам придется создавать уведомление самостоятельно.

Мы можем получить доступ к данным следующим образом:

          override fun onMessageReceived(message: RemoteMessage) {
        super.onMessageReceived(message)
        val title = message.data.getOrDefault("title", "")
        val body = message.data.getOrDefault("body", "")
}

FirebaseMessagingService имеет

      public void handleIntent(Intent intent) {
    String action = intent.getAction();
    if (!"com.google.android.c2dm.intent.RECEIVE".equals(action) && !"com.google.firebase.messaging.RECEIVE_DIRECT_BOOT".equals(action)) {
        if ("com.google.firebase.messaging.NEW_TOKEN".equals(action)) {
            this.onNewToken(intent.getStringExtra("token"));
        } else {
            Log.d("FirebaseMessaging", "Unknown intent action: " + intent.getAction());
        }
    } else {
        this.handleMessageIntent(intent);
    }

}

вы можете просто переопределить эту функцию в своем собственном классе обслуживания, который расширяет FirebaseMessagingService.

this.handleMessageIntent(намерение); -> обрабатывает уведомление, когда приложение закрыто/в фоновом режиме. Вы можете удалить эту строку и использовать функции, которые используются в переопределенном методе onMessageRecieved(), чтобы отобразить собственный макет. поэтому вы показываете свой собственный макет как на заднем, так и на переднем плане.

Просто вызовите это в методе onCreate вашего MainActivity:

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

Точка, которая заслуживает выделения, состоит в том, что вы должны использовать сообщение данных - только ключ данных - чтобы вызывать обработчик onMessageReceived, даже когда приложение находится в фоновом режиме. У вас не должно быть никаких других ключей уведомлений в вашей полезной нагрузке, иначе обработчик не будет запущен, если приложение находится в фоновом режиме.

Это упоминается (но не особо подчеркивается в документации FCM) здесь:

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

Используйте сервер приложений и API сервера FCM: задайте только ключ данных. Может быть разборным или неразборным.

У меня возникла та же проблема, и я еще немного покопался в этом. Когда приложение находится в фоновом режиме, в системный трей отправляется уведомление, НО сообщение с данными отправляется на onMessageReceived()
См. https://firebase.google.com/docs/cloud-messaging/downstream.
и https://github.com/firebase/quickstart-android/blob/master/messaging/app/src/main/java/com/google/firebase/quickstart/fcm/MyFirebaseMessagingService.java

Чтобы обеспечить отправку сообщения, в документах говорится: "Используйте сервер приложений и API сервера FCM: задайте только ключ данных. Может быть как разборным, так и неразборчивым".
См. https://firebase.google.com/docs/cloud-messaging/concept-options

Если ваша проблема связана с отображением большого изображения, т.е. если вы отправляете push-уведомление с изображением из консоли Firebase, и оно отображает изображение, только если приложение находится на переднем плане. Решением этой проблемы является отправка push-сообщения только с полем данных. Что-то вроде этого:

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

У меня была эта проблема (приложение не хочет открываться при нажатии на уведомление, если приложение находится в фоновом режиме или закрыто), и проблема была недействительной click_action в теле уведомления попробуйте удалить или изменить его на что-то действительное.

Когда сообщение получено, а ваше приложение находится в фоновом режиме, уведомление отправляется в дополнение к основной деятельности.

Вы можете проверить дополнительные значения в функциях 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);
        }

}

Бэкэнд, с которым я работаю, использует сообщения уведомлений, а не сообщения данных. Поэтому после прочтения всех ответов я попытался извлечь дополнительные сведения из набора намерений, которые приходят к запущенному действию. Но независимо от того, какие ключи я пытался получить из getIntent().getExtras();, значение всегда было нулевым.

Тем не менее, я наконец нашел способ отправлять данные с помощью уведомлений и извлекать их из намерения.

Ключевым моментом здесь является добавление полезных данных в сообщение уведомления.

Пример:

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

Ссылка

Существует два типа сообщений: уведомления и сообщения с данными. Если вы отправляете только сообщение с данными, то в строке сообщения отсутствует объект уведомления. Это будет вызвано, когда ваше приложение в фоновом режиме.

Проверьте ответ @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"
}

Затем, если приложение находится в фоновом режиме, дополнительное намерение по умолчанию получит "данные"

Удачи!

Это предполагаемое поведение, вам нужно установить click_action в наборе данных уведомлений firebase, чтобы иметь возможность получать данные из фона.

Смотрите обновленный ответ здесь: /questions/39595393/kak-obrabatyivat-uvedomleniya-kogda-prilozhenie-v-fonovom-rezhime-v-firebase/63545727#63545727

Другие вопросы по тегам