FirebaseMessagingService: намерение.putExtra() не работает, если приложение не запущено

EDIT3: Хорошо, я обнаружил проблему: если приложение убито, отправка data и notification не вызовет onMessageReceived. notification необходимо установить значение null, если целевым устройством является Android.

Это действительно глупое поведение.

Исходное сообщение:

Я могу успешно получить пакет из намерения, переданного notificationBuilder, в действие при запуске приложения.

Однако, если я убью приложение, уведомление все равно будет работать, но GetExtras() из намерения будет нулевым.

В моем дочернем классе FirebaseMessagingService:

@Override
public void onMessageReceived(RemoteMessage remoteMessage)
{
     Intent intent  = new Intent(this, MainActivity.class);        
     intent.putExtra("key_1","value");
     PendingIntent pendingIntent = PendingIntent.getActivity(this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    //also tried with  PendingIntent.FLAG_CANCEL_CURRENT


     Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
    NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentTitle("title")
            .setContentText("messageBody")
            .setAutoCancel(true)
            .setSound(defaultSoundUri)
            .setContentIntent(pendingIntent);

    NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    notificationManager.notify(0, notificationBuilder.build());

}

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

EDIT: я заменил содержимое метода onMessageReceived следующим образом:

@Override
public void onMessageReceived(RemoteMessage remoteMessage)
{
     // Do nothing
}

Когда приложение работает, ничего не происходит, как и ожидалось, но когда приложение закрывается, отображается уведомление с именем приложения в качестве заголовка и remoteMessage.getNotification().getBody() в качестве текста содержимого.

Кажется, onMessageReceived не уволен. Вместо этого вызывается другая магическая функция...

EDIT2: В соответствии с запросом, это то, что отправляется с сервера:

{
    "data":
     {
          "form_id":"33882606580812",
          "recipientUserId":10500
     }
     ,
     "to":"e0bU2jIVO9g:APA91bHsS-s3G1gQLcTFtRUC77pJUWcZvD7h9NfUgFLD-bFam1S0dddngVcmrQlXR5i6DfTsc69T8JbIrSuzyF1iv0c4ac1gmkwvGVMwZo_yA4KwOh82Nx-weYeL79r79si4qH3QBEgs",
     "notification":
     {
          "body":"you have a new notification",
          "badge":"1",
          "sound":"default"
     },
     "delay_while_idle":false
}

person Akli    schedule 29.09.2016    source источник
comment
Пожалуйста, не могли бы вы поделиться JSON вашего fcm, который вы используете для отправки данных и уведомлений?   -  person Nishant Dubey    schedule 29.09.2016
comment
Также вы размещаете весь этот код здесь? // Check if message contains a data payload. if (remoteMessage.getData().size() > 0) { Log.d(TAG, "Message data payload: " + remoteMessage.getData()); //and your other code i.e intents and all }   -  person Nishant Dubey    schedule 29.09.2016
comment
Можете ли вы сказать мне производителя или модель телефона, на котором вы тестируете это? Потому что многие производители (особенно китайские) имеют в своей архитектуре странные фоновые приложения для уничтожения служб, которые вызывают множество проблем с фоновыми приложениями служб и многим другим. Просто небольшое беспокойство, что даже это может быть проблемой здесь.   -  person Nishant Dubey    schedule 29.09.2016
comment
Возможно, вы правы, я тестирую эмуляторы Visual Studio. Я собираюсь проверить с реальным устройством.   -  person Akli    schedule 29.09.2016
comment
Повторяя первый комментарий, не могли бы вы расширить вопрос с полезной нагрузкой, которую вы отправляете в FCM? Это действительно важно, так как клиент Android ведет себя по-разному в зависимости от того, какие типы полезной нагрузки (данные и/или уведомления) вы включаете.   -  person vzsg    schedule 30.09.2016
comment
@Nishant, не могли бы вы опубликовать Edit3 в качестве ответа? Я думаю, вы указали на это в первый раз.   -  person Akli    schedule 30.09.2016
comment
@Akli, я только что опубликовал. Думаю, теперь вы уже знаете решение. Удачи :)   -  person Nishant Dubey    schedule 30.09.2016
comment
@Akli Пожалуйста, сначала попробуйте отредактированное предложение, которое я только что написал в своем ответе. Если это сработает, вы можете отправлять полезные данные как для уведомлений, так и для данных. Но да, это верно только в том случае, если ваше действие требует от пользователя запуска MainActivity. В противном случае основным решением для onMessageReceived() является путь. Но вы, безусловно, можете перехватить намерение запуска приложения из щелчка уведомления, даже если json имеет полезную нагрузку как для уведомлений, так и для данных.   -  person Nishant Dubey    schedule 01.10.2016


Ответы (2)


Мой первый ответ на ваш вопрос, который я удалил, поскольку мы оба чувствовали, что в вашем случае вызывается onMessageReceived(). Но это то, что есть на самом деле

Метод onMessageReceived() не будет вызываться, если приложение находится в фоновом режиме или убито, а отправленное сообщение содержит полезные данные DATA и NOTIFICATION.

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

что-то вроде этого:

    {
   "to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
   "data" : {
     "Title" : "Title for Notification",
     "body" : "Notification body can go here",
     "Room" : "Something extra"
   },
 }

Надеюсь, это решит вашу проблему.

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

Intent fcmIntent = getIntent();

Но это будет работать только в Launcher Activity, которое запускается щелчком уведомления. Вы можете просто поместить его в метод onCreate().

person Nishant Dubey    schedule 30.09.2016
comment
Спасибо за действительно важную информацию, я узнал, что не нужно использовать его в работе лаунчера. внутри службы firebase вы отправляете эти данные с определенным намерением. там вы можете использовать, но действительно важно, если вы поместите полезную нагрузку уведомления. это не просыпаться и делать то, что вам нужно. работают только данные - person Alp Altunel; 25.10.2019

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

[Исключение 2] Сообщения с уведомлением и полезными данными, как в фоновом, так и в активном режиме. В этом случае уведомление доставляется на панель задач устройства, а полезные данные доставляются в дополнительных элементах намерения. вашей активности в лаунчере.

Это означает, что ваш метод onMessageReceived никогда не вызывается в этом состоянии. Служба FCM внутри создает уведомление, которое запускает ваше основное действие и автоматически передает data полезную нагрузку в пакет намерений.

Вы должны либо правильно обработать эту ситуацию, либо использовать только полезные данные data, чтобы отказаться от встроенного поведения.

person vzsg    schedule 30.09.2016