Firebase FCM уведомления click_action полезная нагрузка

Я пытаюсь открыть конкретное действие, когда пользователь нажимает уведомление, когда приложение находится в фоновом режиме. Из Документов я получил, что click_action должен быть добавлен в полезную нагрузку и фильтр намерений в приложении для его обработки. Но как добавить click_action в уведомления Firebase через Firebase Console? Я открыт для любой другой работы. Спасибо в Advance.

Ответ 1

Если ваше приложение находится в фоновом режиме, Firebase не будет запускать onMessageReceived(). Зачем.....? Понятия не имею. В этой ситуации я не вижу смысла в реализации FirebaseMessagingService.

В соответствии с документами, если вы хотите обработать приход фонового сообщения, вам нужно отправить сообщение "click_action" с вашим сообщением. Но это невозможно, если вы отправляете сообщение с консоли Firebase, только через Firebase API. Это означает, что вам нужно будет создать свою собственную консоль, чтобы маркетинговые люди могли ее использовать. Таким образом, консоль Firebase также совершенно бесполезна!

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

Я предполагаю, что нам придется ждать новых версий и улучшений/исправлений!

Ответ 2

Насколько я могу судить, на данный момент невозможно установить click_action в консоли.

Хотя не является строгим ответом на то, как установить click_action в консоли, вы можете использовать завиток в качестве альтернативы:

curl --header "Authorization: key=<YOUR_KEY_GOES_HERE>" --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\"}}"

Это простой способ проверить сопоставление click_action. Для этого требуется фильтр намерений, подобный тому, который указан в документах FCM:

<intent-filter>
  <action android:name="OPEN_ACTIVITY_1" />
  <category android:name="android.intent.category.DEFAULT" />
</intent-filter>

Ответ 3

Вы можете обрабатывать все свои действия в функции своего сообщения в onMessageReceived() в своей службе, расширяя FirebaseMessagingService. Для этого вам необходимо отправить сообщение, содержащее исключительно данные, используя, например, Advanced REST client в Chrome. Затем вы отправляете POST на https://fcm.googleapis.com/fcm/send используя в "Raw headers":

Content-Type: application/json Авторизация: key = YOUR_PERSONAL_FIREBASE_WEB_API_KEY

И сообщение json в поле "Сырая полезная нагрузка".

Предупреждение. Если в вашем json есть поле "уведомление", ваше сообщение никогда не будет получено, когда приложение будет в фоновом режиме в onMessageReceived(), даже если есть поле данных! Например, делая это, сообщение работает, только если приложение на переднем плане:

{
    "condition": " 'Symulti' in topics || 'SymultiLite' in topics",
    "priority" : "normal",
    "time_to_live" : 0,
    "notification" : {
        "body" : "new Symulti update !",
        "title" : "new Symulti update !",
        "icon" : "ic_notif_symulti"
    },
    "data" : {
        "id" : 1,
        "text" : "new Symulti update !"
    }
}

Чтобы получать ваше сообщение во всех случаях в onMessageReceived(), просто удалите поле "уведомление" из вашего json!

Пример:

{
    "condition": " 'Symulti' in topics || 'SymultiLite' in topics",
    "priority" : "normal",
    "time_to_live" : 0,,
    "data" : {
        "id" : 1,
        "text" : "new Symulti update !",
        "link" : "href://www.symulti.com"
    }
}

и в вашем FirebaseMessagingService:

public class MyFirebaseMessagingService extends FirebaseMessagingService {

    private static final String TAG = "MyFirebaseMsgService";

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
      String message = "";
      obj = remoteMessage.getData().get("text");
      if (obj != null) {
        try {
          message = obj.toString();
        } catch (Exception e) {
          message = "";
          e.printStackTrace();
        }
      }

      String link = "";
      obj = remoteMessage.getData().get("link");
      if (obj != null) {
        try {
          link = (String) obj;
        } catch (Exception e) {
          link = "";
          e.printStackTrace();
        }
      }

      Intent intent;
      PendingIntent pendingIntent;
      if (link.equals("")) { // Simply run your activity
        intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
      } else { // open a link
        String url = "";
        if (!link.equals("")) {
          intent = new Intent(Intent.ACTION_VIEW);
          intent.setData(Uri.parse(link));
          intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        }
      }
      pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
          PendingIntent.FLAG_ONE_SHOT);


      NotificationCompat.Builder notificationBuilder = null;

      try {
        notificationBuilder = new NotificationCompat.Builder(this)
            .setSmallIcon(R.drawable.ic_notif_symulti)          // don't need to pass icon with your message if it already in your app !
            .setContentTitle(URLDecoder.decode(getString(R.string.app_name), "UTF-8"))
            .setContentText(URLDecoder.decode(message, "UTF-8"))
            .setAutoCancel(true)
            .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
            .setContentIntent(pendingIntent);
        } catch (UnsupportedEncodingException e) {
          e.printStackTrace();
        }

        if (notificationBuilder != null) {
          NotificationManager notificationManager =
              (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
          notificationManager.notify(id, notificationBuilder.build());
        } else {
          Log.d(TAG, "error NotificationManager");
        }
      }
    }
}

Наслаждайтесь!

Ответ 4

Это относится к категории обхода, содержащей некоторую дополнительную информацию:

Поскольку уведомления обрабатываются по-разному в зависимости от состояния приложения (foreground/background/not started), я видел лучший способ реализовать вспомогательный класс, в котором выбранная активность запускается на основе пользовательских данных, отправленных в уведомление.

  • когда приложение находится на переднем плане, используйте вспомогательный класс в onMessageReceived
  • Когда приложение находится в фоновом режиме, используйте вспомогательный класс для обработки намерения в основной деятельности onNewIntent (проверьте определенные пользовательские данные).
  • Когда приложение не работает, используйте вспомогательный класс для обработки намерения в основной деятельности onCreate (вызов getIntent для намерения).

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

Таким образом, минимальные пользовательские данные выглядят примерно так:

Key: run_activity
Value: com.mypackage.myactivity

И код для его обработки:

if (intent.hasExtra("run_activity")) {
    handleFirebaseNotificationIntent(intent);
}


private void handleFirebaseNotificationIntent(Intent intent){
    String className = intent.getStringExtra("run_activity");
    startSelectedActivity(className, intent.getExtras());
}

private void startSelectedActivity(String className, Bundle extras){
    Class cls;
    try {
        cls = Class.forName(className);
    }catch(ClassNotFoundException e){
        ...
    }
    Intent i = new Intent(context, cls);

    if (i != null) {
        i.putExtras(extras);
        this.startActivity(i);
    } 
}

Это код для двух последних случаев, startSelectedActivity будет вызываться также из onMessageReceived (первый случай).

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

Ответ 5

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

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

$noti = array
    (
    'icon' => 'new',
    'title' => 'title',
    'body' => 'new msg',
    'click_action' => 'your activity name comes here'
); 

И в вашем android.manifest файле

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

     <activity
                android:name="your activity name">
                <intent-filter>
                    <action android:name="your activity name" />
                   <category android:name="android.intent.category.DEFAULT"/>
               </intent-filter>
   </activity>

Ответ 6

Если ваше приложение находится в фоновом режиме, Firebase не будет запускать onMessageReceived(). onMessageReceived() вызывается, когда приложение находится на переднем плане.  Когда приложение находится в фоновом режиме, метод onMessageReceived() будет вызываться только в том случае, если тело https://fcm.googleapis.com/fcm/send содержит только полезную нагрузку данных. Вот, я просто создал способ создания пользовательского уведомления с намерением, у которого требуется ваша активность. и вызвал этот метод в onMessageRecevied().

В PostMan:

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

header: Авторизация: key = ur key

body --- →

{  "data" : {
      "Nick" : "Mario",
      "Room" : "PoSDenmark",

    },

  "to" : "xxxxxxxxx"

}

в вашем приложении.

class MyFirebaseMessagingService  extends FirebaseMessagingService {

 public void onMessageReceived(RemoteMessage remoteMessage) {
       if (remoteMessage.getData().size() > 0) {
           sendNotification("ur message body") ;
        }
    }
private void sendNotification(String messageBody) {
        Intent intent = new Intent(this, Main2Activity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
                PendingIntent.FLAG_ONE_SHOT);

        Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.ic_stat_ic_notification)
                .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());
    }

 }

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

Ответ 7

Update:

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


Итак, я пытался сделать это в консоли уведомлений Firebase без везения. Поскольку я не могу найти места для размещения значения click_action в консоли, то, что я в основном сделал, чтобы проверить это, заключается в том, чтобы добавить пользовательскую пару "ключ/значение" в "Уведомление" ( "Предварительные параметры" > "Пользовательские данные" ):

Key: click_action
Value: <your_preferred_value>

затем попытался вызвать RemoteMessage.getNotification(). getClickAction() в onMessageReceived(), чтобы узнать, извлекает ли оно правильное значение, но он всегда возвращает null. Поэтому я попытался вызвать RemoteMessage.getData(). Get (< указанный_key > ) и смог получить добавленное значение.

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

Способ поведения клиентского приложения и уведомления зависит от того, как вы его программируете. С учетом сказанного, я думаю, вы можете использовать вышеописанное в качестве обходного пути, используя значение, полученное из getData(), а затем вызывающее сообщение Notification. Надеюсь, это поможет. Ура!: D

Ответ 8

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

Ответ 9

Я ищу эту Firebase, разработку из Google cloud messaging push notification basic, поэтому мы можем использовать учебник, функцию и реализацию gcm в firebase, я использую funtion функции gcm push notification для решения этой проблемы click_action Я использую функцию gcm **

'notificationclick'

** попробуйте сохранить URL-адрес click_action в переменной url, это в server-worker.js

var url =  "";

messaging.setBackgroundMessageHandler(function(payload) {

  console.log('[firebase-messaging-sw.js] Received background message ', payload);
  // Customize notification here
  url = payload.data.click_action;

  const notificationTitle = payload.data.title;
  const notificationOptions = {
    body: payload.data.body , 
    icon: 'firebase-logo.png'
  };

  return self.registration.showNotification(notificationTitle,
      notificationOptions);

});


   //i got this in google cloud messaging push notification


self.addEventListener('notificationclick', function (event) {
  event.notification.close();

  var clickResponsePromise = Promise.resolve();
    clickResponsePromise = clients.openWindow(url);

  event.waitUntil(Promise.all([clickResponsePromise, self.analytics.trackEvent('notification-click')]));
});