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

234

Я работаю с 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"));
        }
    }
}
Cyogenos
источник
В дополнение к телу json, где находится ваш код onTokenRefresh ? Вы завершили настройку Android ?
Като
4
Что вы имеете в виду в json теле уведомления? Кроме того, мой код onTokenRefresh находится внутри моей службы FirebaseInstanceID.
Cyogenos
Можете ли вы опубликовать образец полезной нагрузки, которую вы отправляете?
AL.
Вы также можете проверить эту
ветку

Ответы:

145

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

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

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

getIntent().getExtras();

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

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

Артур Томпсон
источник
6
Есть ли способ установить, click_actionкогда я использую Консоль уведомлений Firebase?
Nii Laryea
6
хорошо, но что, если приложение убито (без переднего плана или фона)?
Мичалу
3
Но как отключить уведомление пользователя об отмене? Потому что, если пользователь откажется от него, это означает, что все данные будут пропущены ... Верно?
Алексей Тимощенко
4
Верный! Таким образом, при отправке уведомлений на Android сопутствующие данные должны быть данными, которые улучшают восприятие уведомлений. Это не должны быть критически важные данные приложения, используйте сообщения данных для данных, которые необходимы приложению, даже если пользователь отклоняет уведомление.
Артур Томпсон
3
Это не совсем правильно. Если сообщение содержит только данные, а не полезную нагрузку уведомления, сообщение ВСЕГДА будет доставлено в onMessageReceive, если приложение находится на переднем плане или нет.
JacksOnF1re
126

Полностью удалите 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());
        }
Зохаб Али
источник
9
Я обнаружил, что если я отправлю только сообщение с данными, то приложение, которое очищено от диспетчера задач, не сможет получать уведомления. Это предполагаемое поведение?
Прабхджот Сингх
2
Это было решение для меня, чтобы получать сообщения в фоновом режиме!
Рэй
5
В Oreo, когда приложение убито, onMessageReceived не вызывается. у меня просто полезная нагрузка только с данными. какое-нибудь обновление у вас есть?
Самир Мангролия
2
Работает как шарм!
ССК
3
Очень люблю тебя за этот ответ: р
Ахмад Арслан
63

этот метод handleIntent () устарел, поэтому обработку уведомления можно выполнить, как показано ниже:

  1. Состояние переднего плана: щелчок уведомления перейдет к ожидающему выполнению намерения, которое вы предоставляете при создании уведомления программно, как это обычно делается с полезной нагрузкой данных уведомления.

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

manas.abrol
источник
Спасибо!!! Я потерял пару дней на эту проблему, и этот спас меня.
Игорь Янкович
действительно идеальное решение!
EduXavier
4
Я обрабатываю логику отображения уведомлений в handleIntent (намерение намерения), однако, когда приложение находится в фоновом режиме, отображаются 2 уведомления, одно из которых я создал, а другое по умолчанию содержит полное сообщение из уведомления.
Joyson
5
Круто, но я не вижу смысла OnMessageReceivedв этом случае!
Алаа АбуЗарифа
8
У меня com.google.firebase: firebase-messaging: 11.6.2 & handleIntent уже окончен. Проверьте stackoverflow.com/questions/47308155/…
Ронак Пория
31

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

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

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

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

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

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

Со стороны сервера уведомление Firebase должно иметь следующий формат :

Серверная сторона должна отправить объект «уведомление» . Недостаток объекта «уведомления» в моем 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. Я нашел это от их команды поддержки.

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

Г-н Саджедул Карим
источник
3
Стоит отметить, что «сообщения с данными» не будут приниматься, если устройство находится в режиме глубокого сна (введено в Android 7.0). будь осторожен с этим!
Самер Дж
30

У меня такая же проблема. Проще использовать «сообщение с данными» вместо «уведомления». Сообщение данных всегда загружает класс 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());
    }
Кут
источник
7
Спасибо. Я изменил свой серверный код и использовал «данные» вместо «уведомления», и теперь он работает отлично,
Махеш Каватия
5
@ Не работайте, только если приложение находится на переднем плане, а не на заднем плане. Можете ли вы помочь мне вызвать это событие в обоих случаях?
Анант Шах
@AnantShah как выглядит ваш POST на сервере Firebase?
Koot
3
Здесь на самом деле три возможных случая. 1) Приложение на переднем плане. 2) Приложение в фоновом режиме. 3) Приложение не работает. Как вы говорите, сообщение «данные» будет получено в первых двух случаях, но не в третьем, когда приложение не запущено. Чтобы удовлетворить все три случая, вам необходимо установить поле «уведомления» в сообщении. (Также неплохо, если вы хотите поддерживать iOS и Android-клиенты)
Стив Мозли
1
Даже если приложение не запущено, я все равно получаю сообщение от сервера о функции onmessagereceived. Я согласен с вами, что лучше использовать «уведомление», если вы тоже хотите поддерживать ios.
Koot
21

В соответствии с документацией 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>
Анкит Адлаха
источник
Где бы я создал намерение и открыл ли он определенную деятельность? Я знаю, что это регистрирует намерение OPEN_ACTIVITY_1 в манифесте, но где я на самом деле это называю?
Cyogenos
1
Проверьте это: firebase.google.com/docs/cloud-messaging/...
Анкит Adlakha
Должны ли мы вызывать активность из интент-фильтров? Или запустить его вручную onMessageReceived?
CoolMind
14

Метод 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

vishnuc156
источник
Наиболее важной частью для людей, страдающих от фоновой проблемы, является удаление свойства «уведомления» из JSON, отправляемого сервером. это решает проблему. Большое спасибо.
Рами М. Муса
13

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

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

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
где использовать этот код открытый класс FirebaseBackgroundService расширяет WakefulBroadcastReceiver @Nagendra Badiganti
создайте класс обслуживания в вашем пакете и зарегистрируйтесь в файле manifest.xml. Убедитесь, что у вас есть фильтр для ваших уведомлений. Поскольку служба запускается для каждого уведомления GCM.
Нагендра Бадиганти
firebase.google.com/docs/cloud-messaging/android/… Я перехожу по этой ссылке, мне нужно добавить этот класс, чтобы получать уведомления. просто отправляю сообщение из firebase первое сообщение .. оно говорит, что завершено, но не получает уведомление @Nagendra Badiganti
1
WakefulBroadcastReceiverустарело начиная с уровня API 26.1.0.
Минору
12

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

Таким образом , в MainActivity.java на OnCreate чек на Extras :

    if (getIntent().getExtras() != null) {
        for (String key : getIntent().getExtras().keySet()) {
            Object value = getIntent().getExtras().get(key);
            Log.d("MainActivity: ", "Key: " + key + " Value: " + value);
        }
    }
Гент Берани
источник
Как я могу получить заголовок, тело и данные уведомления?
Md.Tarikul Islam
1
Спасибо, это ответ. @ Md.Tarikul Ислам, используя onMessageReceived (), как указано в этом вопросе.
felixwcf
7

Переопределите 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);
    }
}
T3H Exi
источник
handleIntent () является окончательным
Ettore
@Ettore Как я могу вызвать функцию handleIntent?
Хирото
Метод вызывается, когда вы получаете сообщение от Firebase, но вы не можете переопределить его, потому что метод объявлен как final. (Firebase 11.6.0)
Ettore
5

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

if(getIntent().getExtras()! = null){
  //do your stuff
}else{
  //do that you normally do
}
Uzair
источник
Если я перейду от mainActivity, как будет работать переход к конкретному действию?
Mac_Play
@Uzair getIntent (). GetExtras () всегда получает значение NULL, есть ли у вас какое-либо другое решение? Когда приложение запускается, метод onMessageReceived не вызывается
user2025187
3

Если приложение находится в фоновом режиме. 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»: «Джон Доу поделился контактом в группе Contact Exchange» в разделе «Полезные данные», вы должны использовать параметр «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());
            }
        }
    }
Hiren
источник
2

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

if (getIntent().getExtras() != null) {
           // Call your NotificationActivity here..
            Intent intent = new Intent(MainActivity.this, NotificationActivity.class);
            startActivity(intent);
        }
Аман Шехар
источник
Если я перейду от mainActivity, как будет работать переход к конкретному действию?
Mac_Play
2

в соответствии с решением от 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);
    }
}
Фрэнк
источник
Я пытаюсь реализовать ваше решение, но метод handleIntent () является окончательным в моей версии SDK (SDK 27), поэтому я не могу переопределить его в своем сервисе ...
matdev
Да, но это не моя вина или какая-либо причина, чтобы дать -1 !!! Очень высокомерно. Он работает до Firebase 11.4.2, затем Google изменил его (сделал этот метод окончательным). Так что теперь вы должны запрограммировать собственное решение с уведомлением.
Фрэнк
Я дал не -1, а +1!
Матдев
Вы сохраняете мою работу: P
amitabha2715
2

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

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);
    }
}
user3587828
источник
handleIntent больше не используется в firebase: 11.8.0 и выше.
Шихаб Уддин
1

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

Октавиан Лари
источник
1

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

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

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

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

n_y
источник
1

Бэкэнд, с которым я работаю, использует сообщения уведомлений, а не сообщения данных. Поэтому после прочтения всех ответов я попытался извлечь дополнительные сведения из набора намерений, которые приходят к запущенному действию. Но независимо от того, какие ключи я пытался получить 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

Ссылка

Вито Валов
источник
1

Если ваша проблема связана с отображением большого изображения, т.е. если вы отправляете 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" }
Arun
источник
Вы потеряли запятую перед "AnotherActivity". Мой андроид вибрирует, но на самом деле ничего не отображается (без текста, без изображения, без нажатия).
Джекаби
1

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

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

}
Санджив С
источник
0

У меня возникла та же проблема, и я еще немного покопался в этом. Когда приложение находится в заднем плане, уведомительное сообщение отправляется в системный трей, а сообщение данных отправляется 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

Для того, чтобы убедиться , что сообщение , которое вы отправляете, говорят документы, « С помощью сервера приложений и сервера API ТСМ:.. Установить ключ данных только может быть либо сборно - разборным или нескладным »
См https://firebase.google.com/ Docs / облако сообщения / концепция-опция # notifications_and_data_messages

Эрик Б.
источник
0

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

Shongsu
источник
0

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

Затем, в случае, если приложение в фоновом режиме, дополнительное задание по умолчанию будет получать «данные»

Удачи!

huynq0911
источник
-1

Просто переопределите метод OnCreate в FirebaseMessagingService. Он вызывается, когда ваше приложение находится в фоновом режиме:

public override void OnCreate()
{
    // your code
    base.OnCreate();
}
Ренцо Сиот
источник
Этот ответ мог бы быть более полезным, если бы вы могли добавить объяснение и ссылку на некоторую документацию. Можете ли вы сказать нам, как это должно помочь?
килокан
@kilokahn Можете ли вы объяснить мне, что вы не понимаете? указанный метод должен быть вставлен в код, который является частью вопроса и полностью отвечает на вопрос. Код для Xamarin, но вы можете просто конвертировать в Java.
Ренцо Сиот
AFAIK Официальная документация ( firebase.google.com/docs/cloud-messaging/android/client ) не говорит о переопределении OnCreate в сервисе, расширяющем FirebaseMessagingService - если у вас есть доступ к документации, которая есть, возможно, вы можете поделиться ссылкой? Кроме того, из вашего ответа не ясно, как переопределение onCreate решает проблему отсутствия вызова onMessageReceived при нажатии на уведомление - отсюда и запрос дополнительной информации.
килокан
В документации не упоминается переопределение метода OnCreate, но он работает, потому что я использую его в производстве. Код, который вы хотели бы вставить в метод onMessageReceived и который, очевидно, служит для выполнения некоторых фоновых операций, может быть выполнен в OnCreate.
Ренцо Сиот
В этом случае подробное описание того, как это работает для вас, может оказаться более полезным, чем просто перечисление решения. Кроме того, недокументированное поведение может произвольно прекратить работу с обновлениями, и кто-то, использующий их, должен быть готов к переработке своего кода, когда это произойдет. Этот отказ от ответственности должен быть вставлен.
Килокан
-1

Есть 2 вида из Firebase кнопочных уведомлений:

1- Уведомление (Показать сообщение) -> - 1.1 Если вы выберете этот вариант, ОС создаст само уведомление, если приложение находится в фоновом режиме, и передаст данные в intent. Тогда клиент должен обработать эти данные.

- 1,2 Если приложение находится в переднем плане , то уведомление будет получено через callback-functionв , FirebaseMessagingServiceи это до клиента , чтобы справиться с этим.

2- Сообщения данных (до 4 тыс. Данных) -> Эти сообщения используются для отправки только данных клиенту (без вывода сообщений), и клиент может обработать их в обоих случаях: фон / передний план через функцию обратного вызова в FirebaseMessagingService

Это в соответствии с официальными документами: https://firebase.google.com/docs/cloud-messaging/concept-options

Balflear
источник