web-dev-qa-db-ja.com

Firebase FCM通知click_actionペイロード

アプリがバックグラウンドにあるときにユーザーが通知をクリックすると、特定のアクティビティを開こうとしています。ドキュメントから、ペイロードにclick_actionを追加し、それを処理するためにアプリにインテントフィルターを追加する必要があることがわかりました。しかし、Firebase Consoleを介してFirebase Notificationsにclick_actionを追加する方法は?私も他の回避策を受け入れています。前もって感謝します。

45
Hariharan B

アプリがバックグラウンドにある場合、FirebaseはonMessageReceived()をトリガーしません。なぜ.....?何も思いつきません。この状況では、FirebaseMessagingServiceを実装しても意味がありません。

ドキュメントによると、バックグラウンドメッセージの到着を処理する場合は、メッセージと共に「click_action」を送信する必要があります。ただし、Firebaseコンソールからメッセージを送信する場合、Firebase APIを介してのみ送信することはできません。つまり、マーケティング担当者がそれを使用できるようにするには、独自の「コンソール」を構築する必要があります。そのため、Firebaseコンソールもまったく役に立ちません!

この新しいツールの背後には本当に優れた、有望なアイデアがありますが、実行に失敗しました。

新しいバージョンと改善/修正を待つ必要があると思います!

51
Bozic Nebojsa

私が知る限り、この時点ではコンソールで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");

コンソールで新しく作成されたトピックを表示するのに数時間かかりますが、FCM APIを使用してメッセージを送信できます。

また、アプリがバックグラウンドにある場合にのみ機能することに注意してください。フォアグラウンドにある場合、FirebaseMessagingServiceの拡張機能を実装する必要があります。 onMessageReceivedメソッドでは、click_actionターゲットに手動で移動する必要があります。

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

先ほど言ったように、現時点ではコンソールから通知ペイロードプロパティにアクセスする方法を見つけることができませんが、この回避策が役立つと思いました。

49
maddesa

FirebaseMessagingServiceを拡張するサービスのonMessageReceived()で、メッセージの機能ですべてのアクションを処理できます。そのためには、たとえば ChromeのAdvanced REST client を使用して、データのみを含むメッセージを送信する必要があります。次に、「[Raw headers]」でPOSTを https://fcm.googleapis.com/fcm/send に送信します。

コンテンツタイプ:application/json承認:key = YOUR_PERSONAL_FIREBASE_WEB_API_KEY

そして、「Raw payload」フィールドのjsonメッセージ。

警告、jsonに「notification」フィールドがある場合、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");
        }
      }
    }
}

楽しい !

25
Maxime Ancelin

これは回避策カテゴリに分類され、追加情報も含まれます。

通知はアプリの状態(フォアグラウンド/バックグラウンド/起動されていない)によって異なる方法で処理されるため、通知メッセージで送信されたカスタムデータに基づいて選択されたアクティビティが起動されるヘルパークラスを実装する最良の方法を見てきました。

  • アプリがフォアグラウンドにある場合、onMessageReceivedのヘルパークラスを使用します
  • アプリがバックグラウンドにある場合、メインアクティビティのonNewIntentでインテントを処理するためにヘルパークラスを使用します(特定のカスタムデータを確認します)
  • アプリが実行されていないときは、メインアクティビティのonCreateでインテントを処理するためにヘルパークラスを使用します(インテントのgetIntentを呼び出します)。

この方法では、click_actionまたはそれ固有のインテントフィルターは必要ありません。また、コードを1回記述するだけで、あらゆるアクティビティを比較的簡単に開始できます。

したがって、最小のカスタムデータは次のようになります。

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

これが最後の2つのケースのコードであり、startSelectedActivityはonMessageReceived(最初のケース)からも呼び出されます。

制限は、インテントエクストラのすべてのデータが文字列であるため、アクティビティ自体で何らかの方法で処理する必要がある場合があります。また、これは単純化されているため、ユーザーに警告せずにフォアグラウンドにあるアプリのアクティビティ/ビューを変更することはおそらくないでしょう。

16
diidu

これは、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>
13
gagan bhutani

アプリがバックグラウンドにある場合、FirebaseはonMessageReceived()をトリガーしません。 onMessageReceived()は、アプリがフォアグラウンドにあるときに呼び出されます。アプリがバックグラウンドにある場合、 https://fcm.googleapis.com/fcm/send の本文にデータペイロードのみが含まれている場合にのみ、onMessageReceived()メソッドが呼び出されます。ここで、メソッドを作成しましたあなたの必要な活動を持つ意図でカスタム通知を構築するために。 onMessageRecevied()でこのメソッドを呼び出しました。

PostManの場合:

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

header:Authorization:key = ur key

本体--- >>

{  "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()メソッドが呼び出されます。そのメソッド内で、カスタム通知を作成しました。 urアプリがバックグラウンドまたはフォアグラウンドであっても機能します。

5
chandan raj

更新:

そのため、確認のために、Firebase Consoleでclick_actionパラメーターを設定することは現在できません。


そのため、私はこれをFirebase Notifications Consoleで不運にもやってみました。コンソールにclick_action値を配置する場所を見つけることができないため、主にこれをテストするために行ったのは、通知(カスタムオプション>カスタムデータ)にカスタムキー/値のペアを追加することです。

Key: click_action
Value: <your_preferred_value>

次に、onMessageReceived()RemoteMessage.getNotification()。getClickAction() を呼び出して、正しい値を取得しているかどうかを確認しましたが、常にnullを返しました。そこで、次に RemoteMessage.getData()。get(<specified_key>) を呼び出して、追加した値を取得することができました。

NOTE:回避策として使用しても大丈夫なのか、それともベストプラクティスに反するのかはわかりません。独自のアプリサーバーを使用することをお勧めしますが、投稿はFirebase Consoleに固有のものです。

クライアントアプリと通知の動作方法は、プログラミング方法によって異なります。とはいえ、上記の回避策としてgetData()から取得した値を使用し、Notificationでthisまたはthatを呼び出すことができると思います。これが何らかの形で役立つことを願っています。乾杯! :D

3
AL.

Firebase Consoleでclick_actionを設定できるようになりました。通知-メッセージ送信-詳細オプションに移動するだけで、キーと値の2つのフィールドがあります。最初のフィールドにclick_actionを入力し、2番目にそのアクションの値を表すテキストを入力します。そして、マニフェストにintent-filterを追加し、コンソールで書いたのと同じ値を彼に与えます。それが実際のclick_actionのシミュレーションです。

1
Atenica