Вот мой манифест:


    
        
    



    
        
    

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

Вот мой onMessageReceived код. Это вызывается, если мое приложение работает на переднем плане, а не в фоновом режиме. Как я могу запустить этот код, когда приложение тоже находится в фоновом режиме?

// [START receive_message]
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    // TODO(developer): Handle FCM messages here.
    // If the application is in the foreground handle both data and notification messages here.
    // Also if you intend on generating your own notifications as a result of a received FCM
    // message, here is where that should be initiated. See sendNotification method below.
    data = remoteMessage.getData();
    String title = remoteMessage.getNotification().getTitle();
    String message = remoteMessage.getNotification().getBody();
    String imageUrl = (String) data.get("image");
    String action = (String) data.get("action");
    Log.i(TAG, "onMessageReceived: title : "+title);
    Log.i(TAG, "onMessageReceived: message : "+message);
    Log.i(TAG, "onMessageReceived: imageUrl : "+imageUrl);
    Log.i(TAG, "onMessageReceived: action : "+action);

    if (imageUrl == null) {
        sendNotification(title,message,action);
    } else {
        new BigPictureNotification(this,title,message,imageUrl,action);
    }
}
// [END receive_message]

Ответы (29)

1. Почему это происходит?

В FCM (Firebase Cloud Messaging) есть два типа сообщений:

  1. Отображать сообщения: эти сообщения вызывают обратный вызов onMessageReceived (), только когда ваше приложение находится на переднем плане
  2. Сообщения с данными: эти сообщения вызывают onMessageReceived () обратный вызов даже, если ваше приложение находится в переднем плане / в фоновом режиме / убито

ПРИМЕЧАНИЕ: Команда Firebase не разработала пользовательский интерфейс для отправки сообщений с данными на твоих устройств пока нет. Вы должны использовать свой сервер для отправки этого типа!



2. Как?

Для этого необходимо выполнить запрос POST по следующему URL-адресу:

POST https://fcm.googleapis.com/fcm/send

Заголовки

  • Ключ: Content-Type, Значение: application / json
  • Ключ: Авторизация, Значение: key =

Тело по темам

{
    "to": "/topics/my_topic",
    "data": {
        "my_custom_key": "my_custom_value",
        "my_custom_key2": true
     }
}

Или, если вы хотите отправить его на определенные устройства

{
    "data": {
        "my_custom_key": "my_custom_value",
        "my_custom_key2": true
     },
    "registration_ids": ["{device-token}","{device2-token}","{device3-token}"]
}


ПРИМЕЧАНИЕ: Убедитесь, что вы не добавляете ключ JSON уведомление
ПРИМЕЧАНИЕ: Чтобы получить ключ сервера, вы можете найти его в консоли firebase: Ваш проект -> настройки -> Настройки проекта -> Обмен сообщениями в облаке -> Ключ сервера

3. Как обрабатывать push-уведомление?

Вот как вы обрабатываете полученное сообщение:

@Override
public void onMessageReceived(RemoteMessage remoteMessage) { 
     Map data = remoteMessage.getData();
     String myCustomKey = data.get("my_custom_key");

     // Manage data
}

У меня была такая же проблема. После некоторого покопания, почему моя MainActivity вызывается с намерением без данных, я понял, что моя активность LAUNCHER (как в Manifest) - это SplashActivity. Там я нашел данные сообщения и отправил их в MainActivity. Работает как шарм. Я верю, что это может кому-то помочь.

Спасибо за все остальные ответы.

Для захвата сообщения в фоновом режиме вам необходимо использовать BroadcastReceiver

import android.content.Context
import android.content.Intent
import android.util.Log
import androidx.legacy.content.WakefulBroadcastReceiver
import com.google.firebase.messaging.RemoteMessage

class FirebaseBroadcastReceiver : WakefulBroadcastReceiver() {

    val TAG: String = FirebaseBroadcastReceiver::class.java.simpleName

    override fun onReceive(context: Context, intent: Intent) {

        val dataBundle = intent.extras
        if (dataBundle != null)
            for (key in dataBundle.keySet()) {
                Log.d(TAG, "dataBundle: " + key + " : " + dataBundle.get(key))
            }
        val remoteMessage = RemoteMessage(dataBundle)
        }
    }

и добавьте это в свой манифест:


        
            
        

Используя этот код, вы можете получить уведомление в фоновом / переднем плане, а также выполнить действие:

//Data should come in this format from the notification
{
  "to": "/xyz/Notifications",
  "data": {
      "key1": "title notification",
      "key2": "description notification"
  }
}

Используйте этот код в приложении:

  @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);
      String key1Data = remoteMessage.getData().get("key1");
      // use key1Data to according to your need
    }

Предоставленные решения в моем случае не сработали.

В конце концов, я выяснил, что некоторые приложения для оптимизации заряда батареи дают пользователям возможность разрешать или блокировать отправку уведомлений приложениями. В моем случае это был Smart Manager от Samsung, который автоматически блокировал мое приложение, как только оно было убито / удалено из списка последних.

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

Ответ июнь 2018 -

Вы должны убедиться, что в сообщении нет ключевого слова «уведомление». Включите только «данные», и приложение сможет обработать сообщение в onMessageReceived, даже если оно находится в фоновом режиме или уничтожено.

Использование облачных функций:

const message = {
    token: token_id,   // obtain device token id by querying data in firebase
    data: {
       title: "my_custom_title",
       body:  "my_custom_body_message"
       }
    }


return admin.messaging().send(message).then(response => {
    // handle response
});

Затем в вашем onMessageReceived () в вашем классе, расширяющем com.google.firebase.messaging.FirebaseMessagingService:

if (data != null) {
  Log.d(TAG, "data title is: " + data.get("title");
  Log.d(TAG, "data body is: " + data.get("body");
}

// build notification using the body, title, and whatever else you want.

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

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

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

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

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

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

Согласно docs

Обработка сообщений в фоновом приложении

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

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

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

      
 
 

Изменить:

На основе этого поток:

Вы не можете установить полезную нагрузку click_action с помощью Firebase Console. Вы можете попробовать протестировать с помощью команды curl или собственного http-сервера

curl --header "Authorization: key=" 
     --header Content-Type:"application/json" https://fcm.googleapis.com/fcm/send  
     -d "{\"to\":\"/topics/news\",\"notification\": 
         {\"title\": \"Click Action Message\",\"text\": \"Sample message\",
            \"click_action\":\"OPEN_ACTIVITY_1\"}}"

У меня возникла та же проблема, и я перекомпилировал библиотеку firebase и запретил ей отправлять уведомления, когда приложение находится в фоновом режиме

* библиотека https://github.com/erdalceylan/com-google-firebase-messaging

 dependencies {
        compile 'com.google.firebase:firebase-core:11.2.0'
        compile 'com.github.erdalceylan:com-google-firebase-messaging:v1-11.2.0'
    }

*

@WorkerThread
public void onMessageReceived(RemoteMessage var1) {
  //your app is in background or foreground all time calling
}

надеюсь помогает. Удачи

Вот более четкие концепции сообщения firebase. Я нашел его в их службе поддержки.

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

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

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

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

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

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

С 2019 года в Google Firebase произошли большие изменения в API. Я имею в виду: 'com.google.firebase: firebase-messaging: 18.0.0'

в 18.0.0 они удалили MyFirebaseInstanceIDService, и вам нужно получить токен в MyFirebaseMessagingService, поэтому вам просто нужно написать:

@Override
public void onNewToken(String token) {
    Log.d(TAG, "Refreshed token: " + token);

}

, а также в вашем AndroidManifest.xml необходимо удалить:


        
            
        
    

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

Добавьте эти строки в тег приложения, чтобы установить собственный значок по умолчанию и собственный цвет:

    

    

    

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

например, если ваш Json такой:

 "data": {
"message": "2",
"title": "1",
"pushType" : "banner",
"bannerLink": "http://www.google.com",
"image" : "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"}

вам просто нужно написать простое намерение, чтобы получить эти значения:

        Bundle extras = intent.getExtras();
        String bannerLink = extras.getString("bannerLink");
        ...
        String channelId = extras.getString("channelId");

Обычно

В FCM (Firebase Cloud Messaging) есть два типа сообщений:

  • Отображаемые сообщения: Эти сообщения вызывают обратный вызов onMessageReceived () только тогда, когда ваше приложение находится на переднем плане

  • Сообщения с данными: Эти сообщения запускают обратный вызов onMessageReceived (), даже если ваше приложение передний план / фон / убито

Сообщения с данными пример:

{ 
  "to": "/path", 
  "data": 
     { 
      "my_custom_key": "my_custom_value", 
      "my_custom_key2": true 
     } 
}

Отображать сообщения пример:

 {
     "notification": {
            "title" : "title",
            "body"  : "body text",
            "icon"  : "ic_notification",
            "click_action" : "OPEN_ACTIVITY_1"
        }
   }

Сторона Android может обрабатывать такие уведомления, как:

public class MyFirebaseMessagingService extends FirebaseMessagingService {
    …

      @Override public void onMessageReceived(RemoteMessage remoteMessage){
           Map data = remoteMessage.getData();
           String myCustomKey = data.get("my_custom_key");
        
       } 

    …

}

Более подробную информацию о FCM вы можете найти здесь: Настройка клиентского приложения Firebase Cloud Messaging на Android

Чтобы библиотека firebase вызывала ваш onMessageReceived () в следующих случаях

  1. Приложение на переднем плане
  2. Приложение в фоновом режиме
  3. Приложение убито

вы не должны указывать ключ JSON уведомление в своем запросе к Firebase API, а вместо этого используйте данные, см. Ниже.

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

{
   "to": "/topics/journal",
   "notification": {
       "title" : "title",
       "text": "data!",
       "icon": "ic_notification"
    }
}

, но вместо этого будет работать

{
  "to": "/topics/dev_journal",
   "data": {
       "text":"text",
       "title":"",
       "line1":"Journal",
       "line2":"刊物"
   }
} 

Обычно сообщение отправляется в аргументе RemoteMessage вместе с вашим объектом данных как Map , тогда вы можете управлять уведомлением в onMessageReceived как в фрагменте здесь

@Override
public void onMessageReceived(RemoteMessage remoteMessage) { 
     Map data = remoteMessage.getData();

     //you can get your text message here.
     String text= data.get("text");


     NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
        // optional, this is to make beautiful icon
             .setLargeIcon(BitmapFactory.decodeResource(
                                    getResources(), R.mipmap.ic_launcher))  
        .setSmallIcon(smallIcon)  //mandatory
      .......
    /*You can read more on notification here:
    https://developer.android.com/training/notify-user/build-notification.html
    https://www.youtube.com/watch?v=-iog_fmm6mE
    */
}

Согласно документации firebase в send downstream, используя firebase, существует 2 типа полезной нагрузки:

  1. данные

    Этот параметр определяет настраиваемые пары "ключ-значение" полезной нагрузки сообщения. Клиентское приложение отвечает за обработку сообщений с данными. Сообщения с данными содержат только настраиваемые пары "ключ-значение".

  2. уведомление

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

Когда вы находитесь на переднем плане, вы можете получить данные внутри FCM, используя onMessageReceived (), вы можете получить свои данные из data payload.

data = remoteMessage.getData();
String customData = (String) data.get("customData");

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

{
  "notification": {
        "title" : "title",
        "body"  : "body text",
        "icon"  : "ic_notification",
        "click_action" : "OPEN_ACTIVITY_1"
       }
}

Это уведомление полезная нагрузка используется, когда вы хотите автоматически отображать уведомление на панели задач, когда ваше приложение находится в фоновом режиме. Чтобы получать данные уведомления, когда ваше приложение работает в фоновом режиме, вы должны добавить click_action внутри notification payload.

Если вы хотите открыть приложение и выполнить определенное действие [в фоновом режиме], установите click_action в полезных данных уведомления и сопоставьте его с фильтром намерений в действии, которое вы хотите запустить. Например, установите для click_action значение OPEN_ACTIVITY_1, чтобы активировать фильтр намерений, подобный следующему:


  
  

Поместите этот фильтр намерений в свой манифест внутри одного из тегов активности. Когда вы щелкаете уведомление, оно откроет приложение и сразу перейдет к действию, которое вы определяете в click_action, в данном случае «OPEN_ACTIVTY_1». И внутри этого действия вы можете получить данные по:

Bundle b = getIntent().getExtras();
String someData = b.getString("someData");

Я использую FCM для своего приложения для Android и использую обе полезные данные. Вот пример JSON, который я использую:

{
  "to": "FCM registration ID",
  "notification": {
    "title" : "title",
    "body"  : "body text",
    "icon"  : "ic_notification",
    "click_action" : "OPEN_ACTIVITY_1"
   },
   "data": {
     "someData"  : "This is some data",
     "someData2" : "etc"
   }
}

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

Шагов

  1. Установить расширение Advanced Rest Client для Google Chrome enter image description here

  2. Добавьте следующие заголовки

    Ключ: Content-Type, Значение: application / json

    Ключ: Авторизация, Значение: key = "ключ вашего сервера" enter image description here

  3. Добавить тело

    • При использовании тем:

      {
          "в": "/ themes / имя_темы",
          "данные": {
          "ключ1": "значение1",
          "ключ2": "значение2",
          }
      }
      
    • При использовании регистрационного идентификатора:

      {
          "registration_ids": "[{" id "}, {id1}]",
          "данные": {
          "ключ1": "значение1",
          "ключ2": "значение2",
           }
      }
      

Вот и все !. Теперь послушайте обратный вызов onMessageReceived, как обычно.

@Override
public void onMessageReceived(RemoteMessage remoteMessage) { 
     Map data = remoteMessage.getData();
     String value1 = data.get("key1");
     String value2 = data.get("key2");
}

Простой способ отправлять сообщения, даже если приложение находится в фоновом или переднем плане, как показано ниже: - Чтобы отправить сообщение с помощью API, вы можете использовать инструмент под названием AdvancedREST Client, его расширение chrome, и отправить сообщение со следующими параметрами.

Остаточный клиентский инструмент Ссылка: https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofddffdnphfgcellkdfbfbjeloo

используйте этот URL: - https://fcm.googleapis.com/fcm/send Тип содержимого: приложение / json Авторизация: ключ = ключ вашего сервера от или ключ авторизации (см. Ссылку ниже)

{ "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 и нажав кнопку «Учетные данные» в левом меню вашего проекта. Среди перечисленных ключей API ключ сервера будет вашим ключом авторизации.

И вам нужно указать tokenID получателя в разделе «Кому» вашего POST-запроса, отправленного с использованием API.

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

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

  1. Добавьте фильтр намерений вот так:

     
       
            <действие android: name = ". MainActivity" />
            
       
    

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

  1. Отправлять уведомления в следующем формате:

     {
      "уведомление" : {
             "click_action": ".MainActivity",
             "body": "новое обновление Symulti!",
             "title": "новое обновление Symulti!",
             "icon": "ic_notif_symulti"},
      "данные": { ... },
      "в": "c9Vaa3ReGdk: APA91bH-AuXgg3lDN2WMcBrNhJZoFtYF9"}
    

Ключ здесь - добавить

"click_action" : ".MainActivity"

, где .MainActivity - это действие с фильтром намерений , которое вы добавили на шаге 1.

  1. Получить данные информацию из уведомления в onCreate .MainActivity:

     protected void onCreate (Bundle savedInstanceState) {
         super.onCreate (savedInstanceState);
         setContentView (R.layout.activity_main);
         // получаем данные уведомления
         Пакет bundle = getIntent (). GetExtras ();
         if (bundle! = null) {
            // пакет должен содержать всю информацию, отправленную в поле "данные" уведомления
         }
     }
    

И это должно быть все, что вам нужно сделать. Надеюсь, это кому-нибудь поможет :)

Простое резюме вроде этого

  • , если ваше приложение работает;

    onMessageReceived ()
    

- триггеры.

  • , если ваше приложение не запущено (убито смахиванием);

    onMessageReceived ()
    

не запускается и не доставляется напрямую. Если у вас есть специальная пара "ключ-значение". Они не работают из-за того, что onMessageReceived () не работает.

Я нашел вот так;

В своей активности запуска поместите эту логику,

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState, R.layout.activity_splash);

    if (getIntent().getExtras() != null && getIntent().getExtras().containsKey("PACKAGE_NAME")) {

        // do what you want

        // and this for killing app if we dont want to start
        android.os.Process.killProcess(android.os.Process.myPid());

    } else {

        //continue to app
    }
}

в этом блоке if ищите свои ключи в соответствии с пользовательским интерфейсом firebase.

В этом примере мой ключ и значение, как указано выше; (извините за язык =)) enter image description here

Когда мой код работает, я получаю com.rda.note.

android.os.Process.killProcess(android.os.Process.myPid());

с этой строкой кода я закрыл свое приложение и открыл Google Play Market

удачное кодирование =)

2017 обновленный ответ

Вот четкий ответ из документов по этому поводу:

enter image description here

Согласно документации: 17.05.2017

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

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

Итак, вы должны использовать как уведомление о полезной нагрузке, так и данные:

{
  "to": "FCM registration ID",
  "notification": {
    "title" : "title",
    "body"  : "body text",
    "icon"  : "ic_notification"
   },
   "data": {
     "someData"  : "This is some data",
     "someData2" : "etc"
   }
}

Нет необходимости использовать click_action. Достаточно просто получить exras из намерения по активности LAUNCHER


        
            
        

Код Java должен находиться в методе onCreate на MainActivity:

Intent intent = getIntent();
if (intent != null && intent.getExtras() != null) {
    Bundle extras = intent.getExtras();
    String someData= extras.getString("someData");
    String someData2 = extras.getString("someData2");
}

Вы можете протестировать как уведомление о полезной нагрузке, так и данные из Консоли уведомлений Firebase. Не забудьте заполнить поля пользовательских данных в разделе «Дополнительные параметры»

со сценариями разобрался,

Когда приложение находится на переднем плане, onMessageReceived () метод вызывается из FirebaseService. Таким образом, будет вызван pendingIntent, определенный в классе службы.

И когда приложение находится в фоне, вызывается первое действие.

Теперь, если вы используете splash activity, тогда обязательно имейте в виду, что splashactivity будет вызываться, иначе, если splashActivity отсутствует, то что угодно первое действие будет вызываться.

Затем вам нужно проверить getIntent () из firstActivity, чтобы узнать, есть ли у него бандл. Если все в порядке, вы увидите, что бандл есть с заполненными значениями. Если значение в теге данных , отправленном с сервера, выглядит следующим образом,

"data": {
    "user_name": "arefin sajib",
    "value": "user name notification"
  }

Тогда в первом действии вы увидите, существует действительное намерение (getIntent () не равно null), действительный пакет и внутри пакета, будет весь упомянутый выше JSON с данными как ключ.

Для этого сценария код для извлечения значения будет выглядеть так:

    if(getIntent()!=null){
            Bundle bundle = getIntent().getExtras();
            if (bundle != null) {
                try {
                   JSONObject object = new JSONObject(bundle.getStringExtra("data"));
String user_name = object.optString("user_name");

                } catch (JSONException e) {
                    e.printStackTrace();
                }


            }
        }
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {

}

не вызывается каждый раз, когда он вызывается только тогда, когда приложение находится на открытом воздухе

есть один метод переопределения, этот метод вызывается каждый раз, независимо от того, какое приложение находится на переднем плане или в фоновом режиме или убито, но этот метод доступен с этой версией api firebase

это версия, которую нужно импортировать из Gradle

compile 'com.google.firebase:firebase-messaging:10.2.1'

это метод

@Override
public void handleIntent(Intent intent) {
    super.handleIntent(intent);

    // you can get ur data here 
    //intent.getExtras().get("your_data_key") 


}

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

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

if(getIntent().getExtras() != null && getIntent().getExtras().get("your_data_key") != null) {
String strNotificaiton = getIntent().getExtras().get("your_data_key").toString();

// делай что хочешь .... }

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

{
    "notification": {
        "body": "Cool offers. Get them before expiring!",
        "title": "Flat 80% discount",
        "icon": "appicon",
        "click_action": "activity name" //optional if required.....
    },
    "data": {
        "product_id": 11,
        "product_details": "details.....",
        "other_info": "......."
    }
}

решать вам, как вы хотите предоставить этот ключ данных или вы хотите уведомить обо всем, что вы можете дать ....... что бы вы ни дали здесь с тем же ключом, вы получите эти данные .........

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

В дополнение к вышеперечисленным ответам, Если вы тестируете push-уведомления с помощью FCM console, ключ и объект data не добавляются в пакет push-уведомлений. Таким образом, вы не получите подробное push-уведомление, когда приложение находится в фоновом режиме или убито.

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

Здесь вы добавите ключ data в ваш push-пакет. Итак, подробный толчок будет показан, как и ожидалось. Надеюсь, это поможет немногим.

вы хотите работать onMessageReceived (RemoteMessage remoteMessage) в фоновом режиме, отправляйте только часть данных с уведомлением, это:

"data":    "image": "",    "message": "Firebase Push Message Using API", 

"AnotherActivity": "True", "to": "идентификатор устройства или токен устройства"

Таким образом, onMessageRecivied - это фон вызова, и передний план не требует обработки уведомлений с помощью панели уведомлений о вашей активности запуска. Обрабатывать полезную нагрузку данных с помощью этого:

  public void onMessageReceived(RemoteMessage remoteMessage)
    if (remoteMessage.getData().size() > 0) 
    Log.d(TAG, "Message data payload: " + remoteMessage.getData());      

Я решил эту проблему с помощью широковещательного сообщения.

создать широковещательную рассылку и отправить полезную нагрузку в широковещательном сообщении от сервис-воркера.

затем получите полезную нагрузку внутри приложения и обработайте ее так, как вы хотите.

Я добавил следующий код в firebase-messaging-sw.js,

messaging.onBackgroundmessage((payload)=>{
    console.log("background message detected!!");
    console.log("message : ", payload);
})

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

, поэтому решение состоит в том, что нам придется удалить полезные данные уведомления из полезных данных запроса.

, поэтому я изменил свою полезную нагрузку с

{
    "notification": {
        "title": "Hey there",
        "body": "Subscribe to AMAL MOHAN N youtube channel"
    },
    "to": "your-browser-token",
    "data": {
        "value1": "text",
        "value2": "",
        "value3": "sample3",
        "value4": "sample4"
    }
}
От

до

{
    "to": "your-browser-token",
    "data": {
            "value1": "text",
            "value2": "",
            "value3": "sample3",
            "value4": "sample4"
          }
}

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

Я нашел это на форуме Android, и у меня это сработало! пожалуйста, дайте мне знать, работает ли это для вас.

Работает по состоянию на июль 2019

Android compileSdkVersion 28, buildToolsVersion 28.0.3 и обмен сообщениями firebase: 19.0.1

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

- Приложение на переднем плане:
уведомление получено методом onMessageReceived в моем классе MyFirebaseMessagingService

- Приложение было убито (не работает в фоновом режиме): уведомление отправляется в панель уведомлений автоматически FCM. Когда пользователь касается уведомления, приложение запускается путем вызова действия, в манифесте которого есть android.intent.category.LAUNCHER. Вы можете получить информационную часть уведомления, используя getIntent (). GetExtras () в методе onCreate ().

- Приложение в фоновом режиме: уведомление отправляется в панель уведомлений автоматически FCM. Когда пользователь касается уведомления, приложение выводится на передний план путем запуска действия, в манифесте которого есть android.intent.category.LAUNCHER. Поскольку мое приложение имеет launchMode = "singleTop" в этом действии, метод onCreate () не вызывается, потому что одно действие того же класса уже создано, вместо этого вызывается метод onNewIntent () этого класса, и вы получаете часть данных уведомление там с помощью intent.getExtras ().

Шаги: 1- Если вы определяете основное действие вашего приложения следующим образом:


    
        
        
        
        
    

2- добавьте эти строки в метод onCreate () вашего MainActivity.class

Intent i = getIntent();
Bundle extras = i.getExtras();
if (extras != null) {
    for (String key : extras.keySet()) {
        Object value = extras.get(key);
        Log.d(Application.APPTAG, "Extras received at onCreate:  Key: " + key + " Value: " + value);
    }
    String title = extras.getString("title");
    String message = extras.getString("body");
    if (message!=null && message.length()>0) {
        getIntent().removeExtra("body");
        showNotificationInADialog(title, message);
    }
}

и эти методы к тому же MainActivity.class:

@Override
public void onNewIntent(Intent intent){
    //called when a new intent for this class is created.
    // The main case is when the app was in background, a notification arrives to the tray, and the user touches the notification

    super.onNewIntent(intent);

    Log.d(Application.APPTAG, "onNewIntent - starting");
    Bundle extras = intent.getExtras();
    if (extras != null) {
        for (String key : extras.keySet()) {
            Object value = extras.get(key);
            Log.d(Application.APPTAG, "Extras received at onNewIntent:  Key: " + key + " Value: " + value);
        }
        String title = extras.getString("title");
        String message = extras.getString("body");
        if (message!=null && message.length()>0) {
            getIntent().removeExtra("body");
            showNotificationInADialog(title, message);
        }
    }
}


private void showNotificationInADialog(String title, String message) {

    // show a dialog with the provided title and message
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setTitle(title);
    builder.setMessage(message);
    builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
            dialog.cancel();
        }
    });
    AlertDialog alert = builder.create();
    alert.show();
}

3- создайте класс MyFirebase следующим образом:

package com.yourcompany.app;

import android.content.Intent;
import android.util.Log;

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

public class MyFirebaseMessagingService extends FirebaseMessagingService {


    public MyFirebaseMessagingService() {
        super();
    }

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {

        Log.d(Application.APPTAG, "myFirebaseMessagingService - onMessageReceived - message: " + remoteMessage);

        Intent dialogIntent = new Intent(this, NotificationActivity.class);
        dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        dialogIntent.putExtra("msg", remoteMessage);
        startActivity(dialogIntent);

    }

}

4- создать новый класс NotificationActivity.class следующим образом:

package com.yourcompany.app;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.view.ContextThemeWrapper;

import com.google.firebase.messaging.RemoteMessage;

public class NotificationActivity extends AppCompatActivity {

private Activity context;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    context = this;
    Bundle extras = getIntent().getExtras();

    Log.d(Application.APPTAG, "NotificationActivity - onCreate - extras: " + extras);

    if (extras == null) {
        context.finish();
        return;
    }

    RemoteMessage msg = (RemoteMessage) extras.get("msg");

    if (msg == null) {
        context.finish();
        return;
    }

    RemoteMessage.Notification notification = msg.getNotification();

    if (notification == null) {
        context.finish();
        return;
    }

    String dialogMessage;
    try {
        dialogMessage = notification.getBody();
    } catch (Exception e){
        context.finish();
        return;
    }
    String dialogTitle = notification.getTitle();
    if (dialogTitle == null || dialogTitle.length() == 0) {
        dialogTitle = "";
    }

    AlertDialog.Builder builder = new AlertDialog.Builder(new ContextThemeWrapper(context, R.style.myDialog));
    builder.setTitle(dialogTitle);
    builder.setMessage(dialogMessage);
    builder.setPositiveButton(getResources().getString(R.string.accept), new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
            dialog.cancel();
        }
    });
    AlertDialog alert = builder.create();
    alert.show();

}

}

5- Добавьте эти строки в манифест приложения внутри тегов

    
        
            
        
    

    

     

    

    

6- добавьте эти строки в свой метод onCreate () Application.java или в метод onCreate () MainActivity.class:

      // notifications channel creation
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
      // Create channel to show notifications.
      String channelId = getResources().getString("default_channel_id");
      String channelName = getResources().getString("General announcements");
      NotificationManager notificationManager = getSystemService(NotificationManager.class);
      notificationManager.createNotificationChannel(new NotificationChannel(channelId,
              channelName, NotificationManager.IMPORTANCE_LOW));
  }

Готово.

Теперь, чтобы это хорошо работало в трех упомянутых сценариях, вы должны отправить уведомление из веб-консоли Firebase следующим образом:

В разделе уведомлений: Название уведомления = заголовок для отображения в диалоговом окне уведомления (необязательно) Текст уведомления = Сообщение для показа пользователю (обязательно) Затем в разделе Target: Приложение = ваше приложение для Android и в разделе «Дополнительные параметры»: Канал уведомлений Android = default_channel_id Пользовательские данные ключ: значение заголовка: (здесь тот же текст, что и в поле заголовка в разделе уведомлений) key: body value: (здесь тот же текст, что и в поле сообщения в разделе уведомлений) ключ: click_action значение: .MainActivity Звук = Отключено
Истекает = 4 недели

Вы можете отладить его в эмуляторе с API 28 с Google Play.

Удачного кодирования!

Спасибо всем за ваши ответы. Но я решил это, отправив сообщение с данными вместо отправки Уведомление. Код сервера

 'here is a message. message',
 'title'        => 'This is a title. title',
 'subtitle' => 'This is a subtitle. subtitle',
 'tickerText'   => 'Ticker text here...Ticker text here...Ticker text 
 here',
 'vibrate'  => 1,
 'sound'        => 1,
 'largeIcon'    => 'large_icon',
 'smallIcon'    => 'small_icon'

);

$fields = array

(
  'registration_ids'    => $registrationIds,
  'data'            => $msg

);
$headers = array

(
  'Authorization: key=' . API_ACCESS_KEY,
 'Content-Type: application/json'

);


$ch = curl_init();

curl_setopt( $ch,CURLOPT_URL, 'https://android.googleapis.com/gcm/send' 
);

curl_setopt( $ch,CURLOPT_POST, true );

curl_setopt( $ch,CURLOPT_HTTPHEADER, $headers );

curl_setopt( $ch,CURLOPT_RETURNTRANSFER, true );

curl_setopt( $ch,CURLOPT_SSL_VERIFYPEER, false );

curl_setopt( $ch,CURLOPT_POSTFIELDS, json_encode( $fields ) );

$result = curl_exec($ch );

curl_close( $ch );

echo $result;

?>

И поймал Данные в onMessageReceived

public class MyFirebaseMessagingService extends FirebaseMessagingService     {

  private static final String TAG = "MyFirebaseMsgService";

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    Log.d(TAG, "From: " + remoteMessage.getFrom());

    // Check if message contains a data payload.
    if (remoteMessage.getData().size() > 0) {
        Log.d(TAG, "Message data payload: " + remoteMessage.getData());

      sendNotification(remoteMessage.getData().get("message"));
     }
   // Check if message contains a notification payload.
    else if (remoteMessage.getNotification() != null) {
        Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
    sendNotification(remoteMessage.getNotification().getBody());
    }


}
   private void sendNotification(String messageBody) {
    Intent intent = new Intent(this, Notify.class).putExtra("msg",messageBody);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
            PendingIntent.FLAG_ONE_SHOT);

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

    NotificationManager notificationManager =
            (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

    notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
}

Согласно OAUTH 2.0:

В этом случае возникнет проблема с аутентификацией из-за того, что FCM теперь использует OAUTH 2

Итак, я прочитал документацию по firebase, и, согласно документации, новый способ отправки сообщения с данными:

POST: https://fcm.googleapis.com/v1/projects/YOUR_FIREBASEDB_ID/messages:send

Заголовки

Key: Content-Type, Value: application/json

Auth

Bearer YOUR_TOKEN 

Пример тела

{
   "message":{
    "topic" : "xxx",
    "data" : {
         "body" : "This is a Firebase Cloud Messaging Topic Message!",
         "title" : "FCM Message"
          }
      }
 }

В URL-адресе указан идентификатор базы данных, который вы можете найти на консоли firebase. (Настройки проекта Go)

А теперь возьмем наш токен (действует только 1 час):

Сначала в консоли Firebase откройте Настройки> Учетные записи служб. Щелкните Generate New Private Key, надежно сохраните файл JSON, содержащий ключ. Мне был нужен этот JSON-файл для авторизации запросов к серверу вручную. Скачал.

Затем я создаю проект node.js и использую эту функцию для получения своего токена;

var PROJECT_ID = 'YOUR_PROJECT_ID';
var HOST = 'fcm.googleapis.com';
var PATH = '/v1/projects/' + PROJECT_ID + '/messages:send';
var MESSAGING_SCOPE = 'https://www.googleapis.com/auth/firebase.messaging';
var SCOPES = [MESSAGING_SCOPE];

  router.get('/', function(req, res, next) {
      res.render('index', { title: 'Express' });
      getAccessToken().then(function(accessToken) {
        console.log("TOKEN: "+accessToken)
      })

    });

function getAccessToken() {
return new Promise(function(resolve, reject) {
    var key = require('./YOUR_DOWNLOADED_JSON_FILE.json');
    var jwtClient = new google.auth.JWT(
        key.client_email,
        null,
        key.private_key,
        SCOPES,
        null
    );
    jwtClient.authorize(function(err, tokens) {
        if (err) {
            reject(err);
            return;
        }
        resolve(tokens.access_token);
    });
});
}

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

2022 WebDevInsider