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

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

13 ответов

Решение

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

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

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

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

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

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

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>

Это также использует темы, чтобы установить аудиторию. Чтобы это работало, вам нужно подписаться на тему "Новости".

FirebaseMessaging.getInstance().subscribeToTopic("news");

Даже если для просмотра вновь созданной темы в консоли требуется несколько часов, вы все равно можете отправлять ей сообщения через интерфейс API FCM.

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

    @Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    //This will give you the topic string from curl request (/topics/news)
    Log.d(TAG, "From: " + remoteMessage.getFrom());
    //This will give you the Text property in the curl request(Sample Message): 
    Log.d(TAG, "Notification Message Body: " + remoteMessage.getNotification().getBody());
    //This is where you get your click_action 
    Log.d(TAG, "Notification Click Action: " + remoteMessage.getNotification().getClickAction());
    //put code here to navigate based on click_action
}

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

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

Тип контента: приложение /json Авторизация: ключ =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's 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");
        }
      }
    }
}

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

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

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

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

Ну, это ясно из документации 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>

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

В PostMan:

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

заголовок: Авторизация: ключ = ваш ключ

тело --->>

{  "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 (). внутри этого метода я только что сделал пользовательское уведомление. это будет работать, даже если ваше приложение является фоновым или передним.

Обновить:

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


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

Key: click_action
Value: <your_preferred_value>

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

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

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

В Интернете просто добавьте URL-адрес, который хотите открыть:

{  
  "condition": "'test-topic' in topics || 'test-topic-2' in topics",  
  "notification": {
            "title": "FCM Message with condition and link",
            "body": "This is a Firebase Cloud Messaging Topic Message!",            
            "click_action": "https://yoururl.here"
        }
}

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

Одно простое решение - в ссылке параметров fcm удалить https или http, указать любой другой контент, нажатие на уведомление будет перенаправлено в приложение.

Есть двойной метод для уведомления об обмене сообщениями fcm fcm и уведомления приложения: сначала ваше приложение получает только уведомление о сообщении с телом, заголовком, и вы можете добавить цвет, вибрацию не работает, звук по умолчанию. во втором вы можете полностью контролировать, что происходит, когда вы получаете пример сообщенияonMessageReciever(RemoteMessage rMessage){ notification.setContentTitle(rMessage.getData().get("yourKey")); }вы получите данные с помощью (yourKey), но не из сообщения fcm, которое от облачных функций fcm

Допустим, я хочу перейти кwww.aaa.com/news/post/41

Добавлять"click_action":"/news/post/41"к вашему ключу уведомлений. Например:

      "notification":{
    "title":"   Greetings",
    "body":"This is okay",
    "click_action":"/news/post/41"

}

Работает даже в фоновом режиме. Если у вас есть приложение PWA, оно тоже работает; Я не тестировал его в iOS или собственном приложении для Android.

Я смотрю, что это Firebase, разработка из push-уведомлений облачных сообщений Google, так что мы можем использовать учебник, функцию и реализацию gcm в firebase, я использую функцию функции push-уведомлений gcm, чтобы решить эту проблему 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')]));
});