300

私は Firebase を使用しており、アプリがバックグラウンドにあるときにサーバーからアプリに通知を送信することをテストしています。通知は正常に送信され、デバイスの通知センターにも表示されますが、通知が表示されたとき、または通知をクリックしても、FCMessagingService 内の onMessageReceived メソッドが呼び出されることはありません。

アプリがフォアグラウンドにあるときにこれをテストしたところ、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"));
        }
    }
}
4

28 に答える 28

163

notificationサーバー リクエストからフィールドを完全に削除します。送信のみdataして処理しonMessageReceived()ます。それ以外の場合onMessageReceived()は、アプリがバックグラウンドまたは強制終了されたときにトリガーされません。

"priority": "high"通知リクエストにフィールドを含めることを忘れないでください。ドキュメントによると、データ メッセージは通常の優先度で送信されるため、すぐには到着しません。それも問題になる可能性があります。

これが私がサーバーから送信しているものです

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

したがって、このようにデータを受け取ることができますonMessageReceived(RemoteMessage message)....IDを取得する必要があるとしましょう

Object obj = message.getData().get("id");
        if (obj != null) {
            int id = Integer.valueOf(obj.toString());
        }
于 2016-10-17T10:14:35.810 に答える
67

このメソッド handleIntent() は廃止されたため、通知の処理は次のように実行できます。

  1. フォアグラウンド状態: 通知のクリックは、通常、通知のデータ ペイロードで作成されるため、プログラムで通知を作成するときに提供する保留中のインテントのアクティビティに移動します。

  2. バックグラウンド/キル状態 - ここでは、システム自体が通知ペイロードに基づいて通知を作成し、その通知をクリックすると、アプリケーションのランチャー アクティビティに移動し、ライフサイクル メソッドのいずれかでインテント データを簡単に取得できます。

于 2017-05-09T12:01:11.277 に答える
39

これは、firebase メッセージに関するより明確な概念です。サポートチームから見つけました。

Firebase には 3 つのメッセージ タイプがあります

通知メッセージ: 通知メッセージはバックグラウンドまたはフォアグラウンドで機能します。アプリがバックグラウンドの場合、通知メッセージはシステム トレイに配信されます。アプリがフォアグラウンドにある場合、メッセージはonMessageReceived()またはdidReceiveRemoteNotificationコールバックによって処理されます。これらは基本的に、表示メッセージと呼ばれるものです。

データ メッセージ: Android プラットフォームでは、データ メッセージはバックグラウンドとフォアグラウンドで機能します。データ メッセージは onMessageReceived() によって処理されます。ここでのプラットフォーム固有の注意: Android では、アクティビティの起動に使用されるインテントでデータ ペイロードを取得できます。詳しく説明すると、 があれば、からのみこの"click_action":"launch_Activity_1"インテントを取得できます。getIntent()Activity_1

通知とデータ ペイロードの両方を含むメッセージ: バックグラウンドでは、アプリは通知トレイで通知ペイロードを受信し、ユーザーが通知をタップしたときにのみデータ ペイロードを処理します。フォアグラウンドでは、アプリは両方のペイロードが利用可能なメッセージ オブジェクトを受け取ります。次に、click_action パラメーターは、データ ペイロードではなく、通知ペイロードでよく使用されます。データ ペイロード内で使用する場合、このパラメーターはカスタムのキーと値のペアとして扱われるため、意図したとおりに動作させるにはカスタム ロジックを実装する必要があります。

また、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 メッセージに関するより明確な概念です。サポートチームから見つけました。

詳細については、私のこのスレッドこのスレッドを参照してください

于 2016-08-27T09:20:51.863 に答える
31

私も同じ問題を抱えていました。「通知」の代わりに「データ メッセージ」を使用する方が簡単です。データ メッセージは常に onMessageReceived クラスをロードします。

そのクラスでは、notificationbuilder を使用して独自の通知を作成できます。

例:

 @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());
    }
于 2016-05-26T21:29:20.637 に答える
28

Firebase Cloud Messaging のドキュメントによると、Activity がフォアグラウンドにある場合、onMessageReceived が呼び出されます。アクティビティがバックグラウンドまたは閉じている場合、アプリ ランチャー アクティビティの通知センターに通知メッセージが表示されます。アプリがバックグラウンドにある場合は、次のように firebase メッセージングの REST サービス API を呼び出して、通知のクリックでカスタマイズされたアクティビティを呼び出すことができます。

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>
于 2016-06-02T18:01:40.783 に答える
10

私のために作品の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);
    }
}
于 2017-10-04T09:13:08.060 に答える
7

デフォルトでは、アプリがバックグラウンドで通知をクリックすると、アプリのLauncher アクティビティが起動されます。通知にデータ部分がある場合は、次のように同じアクティビティで処理できます。

if(getIntent().getExtras()! = null){
  //do your stuff
}else{
  //do that you normally do
}
于 2016-06-18T05:34:04.183 に答える
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
  }
}

:上記のコードでこの行を参照してください
"text": "John Doe shared a contact in the group Contact Exchange" in Data payload メッセージの説明などには、「body」または「message」パラメータの代わりに「text」パラメータを使用する必要がありますテキストを使いたい。

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());
            }
        }
    }
于 2017-12-07T09:51:45.703 に答える
1

強調する必要がある点は、アプリがバックグラウンドにある場合でも呼び出される onMessageReceived ハンドラーを取得するには、データ メッセージ (データ キーのみ) を使用する必要があることです。ペイロードに他の通知メッセージ キーを含めないでください。そうしないと、アプリがバックグラウンドにある場合にハンドラーがトリガーされません。

ここで言及されています(ただし、FCMドキュメントではそれほど強調されていません):

https://firebase.google.com/docs/cloud-messaging/concept-options#notifications_and_data_messages

アプリ サーバーと FCM サーバー API を使用する:データ キーのみを設定します。折りたたみ可能または折りたたみ不可のいずれかです。

于 2016-09-18T10:33:19.660 に答える
1

私はこの問題を抱えていました(アプリがバックグラウンドまたは閉じている場合、アプリは通知クリックで開きたくない)、問題はclick_action通知本文で無効でした。削除するか、有効なものに変更してみてください。

于 2016-05-23T14:11:18.887 に答える
1

私が使用しているバックエンドは、データ メッセージではなく通知メッセージを使用しています。そのため、すべての回答を読んだ後、起動されたアクティビティに含まれるインテントのバンドルからエクストラを取得しようとしました。しかし、どのキーを から取得しようとしてもgetIntent().getExtras();、値は常に null でした。

しかし、最終的に通知メッセージを使用してデータを送信し、インテントから取得する方法を見つけました。

ここで重要なのは、データ ペイロードを通知メッセージに追加することです。

例:

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

参照

于 2016-11-24T22:27:04.900 に答える
0

私は同じ問題を抱えていて、これについてさらに掘り下げました。アプリがバックグラウンドにある場合、通知メッセージ はシステム トレイに送信されますが、データ メッセージ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.javaonMessageReceived()

送信しているメッセージを確実にするために、ドキュメントには、「アプリ サーバーと FCM サーバー API を使用します。データ キーのみを設定します。折りたたみ可能または折りたたみ不可のいずれかにすることができます。https://firebase.google.com/
を参照してください。 docs/cloud-messaging/concept-options#notifications_and_data_messages

于 2016-07-19T19:47:21.807 に答える