Firebase onMessageReceived не викликається, коли додаток у фоновому режимі


232

Я працюю з 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"));
        }
    }
}

Окрім тіла json, де ваш код onTokenRefresh ? Ви завершили налаштування Android ?
Като

4
Що ви маєте на увазі json тіло сповіщення? Також мій код onTokenRefresh знаходиться в моїй службі FirebaseInstanceID.
Кіогенос

Чи можете ви опублікувати зразок корисного навантаження, який ви надсилаєте?
АЛ.


Ви також можете перевірити цю нитку stackoverflow.com/questions/39046270 / ...
Md . Sajedul Karim

Відповіді:


144

Це працює за призначенням, повідомлення сповіщень надсилаються до вашого зворотного дзвінка onMessageReceived лише тоді, коли ваша програма стоїть на передньому плані. Якщо ваша програма знаходиться у фоновому режимі або закрита, у центрі сповіщень відображається повідомлення про сповіщення, а будь-які дані з цього повідомлення передаються до наміру, який запускається в результаті натискання користувачем сповіщення.

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

Коли запуск буде запущений, ви можете використовувати

getIntent().getExtras();

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

Більше про повідомлення про сповіщення див. У документах .


6
Чи є спосіб встановити, click_actionколи я використовую консоль сповіщення Firebase?
Нія Ларіє

6
ОК, але що робити, якщо додаток буде вбито (немає переднього плану чи фону)?
michalu

3
Але як відключити сповіщення про відмову від користувача? Тому що якщо користувач відкине його, це означає, що всі дані будуть пропущені ... Так?
Олексій Тимощенко

4
Правильно! Тож при надсиланні повідомлень про сповіщення Android, супутні дані повинні бути даними, які покращують досвід сповіщення. Це не повинні бути важливі дані програми, використовувати дані даних для даних, необхідних додатку, навіть якщо користувач відхиляє сповіщення.
Артур Томпсон

3
Це не зовсім правильно. Якщо повідомлення містить лише дані, а не корисне навантаження сповіщення, воно завжди буде доставлено на onMessageReceive, якщо додаток на передньому плані чи ні.
JacksOnF1re

125

Видаліть 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
Я виявив, що якщо я надішлю лише повідомлення даних, тоді додаток, який очищено від диспетчера завдань, не зможе отримати сповіщення. Це цільова поведінка?
Prabhjot Singh

2
Це було рішенням для мене, щоб отримувати повідомлення у фоновому режимі!
Рей Хулха

5
У програмі Oreo, коли програма вбита, onMessageReceived не викликається. у мене просто корисне навантаження тільки з даними. будь-яке оновлення у вас є?
Самір Мангролія

2
Працює як шарм!
ssk

3
Люблю тебе багато за цю відповідь: p
Ахмад Арслан

63

цей метод handleIntent () амортизований, тому обробку сповіщення можна виконати, як показано нижче:

  1. Стан переднього плану: Клацання сповіщення перейде до активних намірів, що очікують на розгляд, які ви здійснюєте, створюючи сповіщення програмно, як це зазвичай створюється із завантаженням даних сповіщення.

  2. Передумови / загиблий стан - Тут система сама створює сповіщення на основі корисного навантаження сповіщень, а натискання на це сповіщення переведе вас до запуску програми програми, де ви можете легко отримати дані про наміри в будь-якому з методів життєвого циклу.


Дякую!!! Я втратив пару днів з цієї проблеми, і ця врятувала мене.
Ігор Янкович

дійсно ідеальне рішення!
EduXavier

4
Я обробляю логіку відображення сповіщень у handleIntent (Намір наміру), однак, коли програма перебуває у фоновому режимі, відображаються 2 повідомлення, одне, яке я створив, та інше за замовчуванням, яке містить ціле повідомлення від повідомлення.
Джойсон

5
Дивовижно, але я не бачу OnMessageReceivedв цьому ніякої користі !?
Алаа АбуЗаріфа

8
У мене com.google.firebase: firebase-повідомлення: 11.6.2 & handleIntent є остаточним now.Check stackoverflow.com/questions/47308155 / ...
Ronak Порія

31

Ось більш чіткі поняття про повідомлення Firebase. Я знайшов це у їхньої групи підтримки.

Firebase має три типи повідомлень :

Повідомлення повідомлень : Повідомлення повідомлень працює на тлі або на передньому плані. Коли програма знаходиться у фоновому режимі, повідомлення-повідомлення надходять у системний трей. Якщо додаток на першому плані, повідомлення обробляє onMessageReceived()абоdidReceiveRemoteNotification зворотні дзвінки. Це, по суті, те, що називають дисплейними повідомленнями.

Інформаційні повідомлення : На платформі Android повідомлення даних може працювати на тлі та на передньому плані. Повідомлення даних буде оброблятися onMessageReceived (). Примітка, що стосується певної платформи, була б такою: На Android, корисне навантаження даних можна отримати в Намір, який використовується для запуску вашої діяльності. Щоб уточнити, якщо у вас є "click_action":"launch_Activity_1", ви можете отримати цей намір getIntent()лише за допомогою Activity_1.

Повідомлення з повідомленнями та корисними навантаженнями : у фоновому режимі програми отримують навантаження сповіщень у лотку сповіщень та обробляють дані корисного навантаження лише тоді, коли користувач натискає на сповіщення. Перебуваючи на передньому плані, ваш додаток отримує об’єкт повідомлення з обома доступними корисними навантаженнями. По-друге, параметр керування кліком часто використовується в корисному навантаженні повідомлень, а не в корисному навантаженні даних. Якщо використовується всередині корисної навантаження даних, цей параметр буде розглядатися як спеціальна пара ключ-значення, і тому вам потрібно буде реалізувати власну логіку, щоб вона працювала за призначенням.

Також я рекомендую вам використовувати метод 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). будьте обережні з тими!
Sameer J

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?
Коот

3
Тут насправді три можливі випадки. 1) Додаток на передньому плані. 2) Додаток у фоновому режимі. 3) Додаток не працює. Як ви кажете, повідомлення "дані" буде отримано в перших двох випадках, але не в третьому випадку, коли додаток не працює. Для задоволення всіх трьох випадків у повідомленні потрібно встановити поле "сповіщення". (Також гарна ідея, якщо ви хочете підтримувати iOS, а також клієнтів Android)
Стів Мозелі,

1
Навіть у додатку не працює, я отримую повідомлення від сервера про функцію onmessage, отримана. Я погоджуюся з вами, що краще використовувати "сповіщення", якщо ви хочете також підтримати ios.
Кот

21

Відповідно до документації Firebase Cloud Messaging-Якщо активність на передньому плані, то onMessageReceived буде викликаний. Якщо активність перебуває у фоновому режимі або закрита, у центрі сповіщень відображається повідомлення про активність запуску програм. Ви можете зателефонувати на свою персоналізовану діяльність при натисканні сповіщення, якщо ваш додаток знаходиться у фоновому режимі, зателефонувавши до служби відпочинку 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 в маніфесті, але де я його справді називаю?
Кіогенос


Чи слід викликати активність із фільтрів намірів? Або запустити його вручну 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


Найважливіша частина людей, які страждають на фонову проблему, - це видалити властивість "сповіщення" з 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);
        }
      }
    }
  }
}

У маніфесті.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.
Nagendra Badiganti

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 Іслам

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

handleIntent () остаточний
Етторе

@Ettore Як я можу викликати функцію handleIntent?
Хірото

Метод викликається, коли ви отримуєте повідомлення від Firebase, але ви не можете його замінити, оскільки метод оголошено остаточним. (Firebase 11.6.0)
Ettore

5

За замовчуванням активність запуску у вашому додатку буде запущено, коли ваш додаток знаходиться у фоновому режимі, і ви натиснете сповіщення, якщо у вас є частина даних із повідомленням, ви можете обробляти його в тій самій дії, як нижче,

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

Якщо я перейду від mainActivity, як буде працювати назад до певної діяльності?
Mac_Play

@Uzair getIntent (). GetExtras () завжди стає недійсним, чи є у вас якесь інше рішення? Коли додаток починається з методу 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
  }
}

ПРИМІТКА . Дивіться цей рядок у наведеному вище коді
"текст": "Джон Доу поділився контактом у групі Контактної біржі" на корисному навантаженні даних, ви повинні використовувати параметр "текст" замість параметрів "тіло" або "повідомлення" для опису повідомлення або будь-якого іншого хочу використовувати текст.

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

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

згідно рішення з t3h Exi, я хотів би розмістити тут чистий код. Просто поставте його в MyFirebaseMessagingService, і все працює добре, якщо програма знаходиться у фоновому режимі. Вам потрібно принаймні скласти com.google.firebase: firebase-обмін повідомленнями: 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!
matdev

Ви врятуєте мою роботу: 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);
    }
}

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: встановіть лише ключ даних . Може бути або розбірним, або нерозбірним.


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

ви втратили кому перед "AnotherActivity". Мій андроїд вібрує, але насправді нічого не відображається (ні тексту, ні зображення, ні натискання).
jekaby

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 сервера FCM. Встановіть лише ключ даних. Може бути розбірним або нерозбірним ".
Див. Https://firebase.google.com/ docs / cloud-messaging / concept-options # notictions_and_data_messages


0

Існує два типи повідомлень: повідомлення сповіщень та повідомлення даних. Якщо ви надсилаєте лише повідомлення даних, це без об’єкта сповіщення у рядку повідомлення. Це буде викликано, коли ваш додаток у фоновому режимі.


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

Тоді, у випадку, якщо додаток у фоновому режимі, додаткові наміри активності за замовчуванням отримають "дані"

Удачі!


-1

Просто перекрийте метод OnCreate FirebaseMessagingService. Він називається, коли ваша програма знаходиться у фоновому режимі:

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

Ця відповідь може бути кориснішою, якщо ви можете додати пояснення та посилання на якусь документацію. Скажіть, будь ласка, як це має допомогти?
kilokahn

@kilokahn Ви можете мені пояснити, чого ви не розумієте? зазначений метод повинен бути вставлений у код, який є частиною питання і повністю відповідає на питання. Код призначений для Xamarin, але його можна просто перетворити на Java.
Renzo Ciot

AFAIK В офіційній документації ( firebase.google.com/docs/cloud-messaging/android/client ) не йдеться про переосмислення OnCreate в службі, що розширює FirebaseMessagingService - якщо у вас є доступ до документації, яка це робить, можливо, ви можете поділитися посиланням? Крім того, з вашої відповіді не зрозуміло, як переосмислення onCreate вирішує проблему onMessageReceived не отримувати виклику, коли натискається сповіщення - отже, запит на отримання додаткової інформації.
kilokahn

Документація не згадує про заміщення методу OnCreate, але він працює, тому що я використовую його у виробництві. Код, який ви хотіли б вставити у метод onMessageReceived і який, очевидно, служить для виконання деяких фонових операцій, може бути виконаний на OnCreate.
Renzo Ciot

У такому випадку, уточнюючи той факт, що це якось спрацювало для вас, може виявитися кориснішим, ніж просто перелічити рішення. Крім того, бездокументована поведінка, ймовірно, може довільно припинити роботу з оновленнями, і хтось, хто їх використовує, повинен бути готовий переробити свій код, коли це станеться. Цю відмову потрібно викласти.
kilokahn

-1

Є 2 види з Firebase кнопкових повідомлень:

1- Повідомлення про повідомлення (Дисплейне повідомлення) -> - 1.1 Якщо ви виберете цей варіант, ОС створить його самоповідомлення, якщо програма знаходиться у фоновому режимі і передасть дані вintent . Тоді клієнт повинен обробляти ці дані.

- 1,2 Якщо додаток знаходиться в передньому плані потім повідомлення буде отримано з допомогою callback-functionвFirebaseMessagingService , і це до клієнта , щоб впоратися з цим.

2- Повідомлення даних (до 4k даних) -> Ці повідомлення використовуються для надсилання клієнту лише даних (мовчки), а клієнт повинен обробляти їх для обох випадків фону / переднього плану за допомогою функції зворотного виклику в FirebaseMessagingService

Це згідно з офіційними документами: https://firebase.google.com/docs/cloud-messaging/concept-options

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.