programing

앱이 백그라운드에 있을 때 메시지 수신 시 Firebase가 호출되지 않음

yellowcard 2023. 7. 9. 11:00
반응형

앱이 백그라운드에 있을 때 메시지 수신 시 Firebase가 호출되지 않음

저는 Firebase에서 작업하고 있으며 앱이 백그라운드에 있는 동안 서버에서 앱으로 알림을 보내는 것을 테스트하고 있습니다.알림이 성공적으로 전송되고 장치의 알림 센터에도 표시되지만 알림이 나타나거나 클릭해도 FC Messaging Service 내의 onMessageReceived 메서드가 호출되지 않습니다.

앱이 포그라운드에 있을 때 테스트를 해보니 onMessageReceived 메서드가 호출되어 모든 것이 정상적으로 작동했습니다.이 문제는 앱이 백그라운드에서 실행될 때 발생합니다.

이것이 의도된 행동입니까, 아니면 제가 이것을 고칠 수 있는 방법이 있습니까?

다음은 나의 FBM 메시징 서비스입니다.

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

이것은 의도한 대로 작동하며, 앱이 포그라운드에 있을 때만 알림 메시지가 메시지 수신 콜백으로 전달됩니다.앱이 백그라운드에 있거나 닫힌 경우 알림 센터에 알림 메시지가 표시되고 사용자가 알림을 누르면 해당 메시지의 데이터가 실행되는 의도로 전달됩니다.

다음을 지정할 수 있습니다.click_action사용자가 알림을 탭할 때 시작해야 하는 의도를 나타내는 JSON.되지 않은 경우 됩니다.click_action은 기본 활동입니다.

의도가 시작되면 다음을 사용할 수 있습니다.

getIntent().getExtras();

알림 메시지와 함께 전송된 데이터가 포함된 집합을 검색합니다.

알림 메시지에 대한 자세한 내용은 문서를 참조하십시오.

서버 요청에서 필드를 완전히 제거합니다.전송만 하고 처리함onMessageReceived()그렇지 않으면 당신의onMessageReceived()앱이 백그라운드에 있거나 삭제된 경우 트리거되지 않습니다.

다음을 포함하는 것을 잊지 마십시오."priority": "high"필드를 선택합니다.문서에 따르면, 데이터 메시지는 일반적인 우선순위로 전송되므로 즉시 도착하지 않습니다. 문제가 될 수도 있습니다.

서버에서 보내는 것은 다음과 같습니다.

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

그래서 당신은 당신의 데이터를 수신할 수 있습니다.onMessageReceived(RemoteMessage message)식으로.. 를 얻어야 . 아이디를 얻어야 한다고 치자.

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

이 메소드 핸들의도()가 감가상각되었으므로 알림 처리는 다음과 같이 수행할 수 있습니다.

  1. 전경 상태:알림을 클릭하면 해당 알림의 데이터 페이로드로 일반적으로 생성된 것처럼 프로그래밍 방식으로 알림을 생성하는 동안 제공하는 보류 중인 의도의 활동으로 이동합니다.

  2. 백그라운드/정지된 상태 - 여기서 시스템 자체가 알림 페이로드를 기반으로 알림을 생성하고 해당 알림을 클릭하면 응용프로그램의 시작 프로그램 활동으로 이동하여 모든 수명 주기 방법으로 의도 데이터를 쉽게 가져올 수 있습니다.

다음은 Firebase 메시지에 대한 보다 명확한 개념입니다.저는 그들의 지원 팀에서 그것을 찾았습니다.

Firebase에는 세 가지 메시지 유형이 있습니다.

알림 메시지 : 알림 메시지는 백그라운드 또는 포그라운드에서 작동합니다.앱이 백그라운드에 있으면 알림 메시지가 시스템 트레이에 전달됩니다.앱이 전경에 있는 경우 메시지는 다음에 의해 처리됩니다.onMessageReceived()또는didReceiveRemoteNotification이러한 으로 표시 이러한 메시지는 기본적으로 표시 메시지라고 합니다.

데이터 메시지:Android 플랫폼에서 데이터 메시지는 배경과 전경에서 작동할 수 있습니다.데이터 메시지는 onMessageReceived()에 의해 처리됩니다.여기서 플랫폼별 참고 사항은 다음과 같습니다. Android의 경우 활동을 시작하는 데 사용된 의도에서 데이터 페이로드를 검색할 수 있습니다.자세히 말하자면, 만약 당신이 가지고 있다면."click_action":"launch_Activity_1"는 다을통해이수검있다습니색할도의를 통해 검색할 수 .getIntent() 한 사람의 서만.Activity_1.

알림데이터 페이로드가 모두 포함된 메시지:백그라운드에서 앱은 알림 트레이에 알림 페이로드를 수신하고 사용자가 알림을 탭할 때만 데이터 페이로드를 처리합니다.포그라운드에서 앱은 두 페이로드를 모두 사용할 수 있는 메시지 개체를 수신합니다.둘째, click_action 매개 변수는 종종 알림 페이로드에 사용되며 데이터 페이로드에는 사용되지 않습니다.데이터 페이로드 내에서 사용되는 경우 이 매개 변수는 사용자 지정 키-값 쌍으로 처리되므로 원하는 대로 작동하려면 사용자 지정 논리를 구현해야 합니다.

또한 데이터 번들을 추출하려면 onMessageReceived 메서드(데이터 메시지 참조)를 사용하는 것이 좋습니다.당신의 논리로 볼 때, 나는 번들 객체를 확인했고 예상되는 데이터 내용을 찾지 못했습니다.여기에 더 명확한 설명을 제공할 수 있는 유사한 사례에 대한 참조가 있습니다.

서버 측에서는 다음과 같은 형식으로 화재 기지 알림을 표시해야 합니다.

서버 측에서 "알림" 개체를 전송해야 합니다.내 시스템에 "알림" 개체가 없음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"
}

자세한 내용은 https://stackoverflow.com/a/39805517 를 참조하십시오.

저도 같은 문제가 있었습니다.'알림' 대신 '데이터 메시지'를 사용하는 것이 더 쉽습니다.데이터 메시지는 항상 Message Received에 클래스를 로드합니다.

이 클래스에서는 알림 작성기로 직접 알림을 만들 수 있습니다.

예:

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

Firebase Cloud Messaging 문서에 따르면 활동이 포그라운드에 있는 경우 수신된 메시지가 호출됩니다.활동이 백그라운드에 있거나 닫힌 경우 앱 실행기 활동에 대한 알림 메시지가 알림 센터에 표시됩니다.파이어베이스 메시징을 위한 휴식 서비스 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>

onMessageReceived(RemoteMessage remoteMessage) 메서드가 다음과 같은 경우에 따라 호출됩니다.

  • FCM 응답 알림데이터 블록 포함:
{
  
"to": "device token list",
  "notification": {
    "body": "Body of Your Notification",
    "title": "Title of Your Notification"
  },
  "data": {
    "body": "Body of Your Notification in Data",
    "title": "Title of Your Notification in Title",
    "key_1": "Value for key_1",
    "image_url": "www.abc.com/xyz.jpeg",
    "key_2": "Value for key_2"
  }
}
  1. 앱 포그라운드:

OnMessage Received(RemoteMessage remoteMessage)가 호출되면 알림 표시줄에 LargeIcon 및 BigPicture가 표시됩니다.알림데이터 블록 모두에서 콘텐츠를 읽을 수 있습니다.

  1. 백그라운드에서 앱:

수신된 메시지(RemoteMessage remoteMessage)가 호출되지 않으면 시스템 트레이가 알림 블록에서 메시지를 수신하고 본문과 제목을 읽으며 알림 표시줄에 기본 메시지와 제목을 표시합니다.

  • 데이터 블록만 있는 FCM 응답:

이 경우 json에서 알림 블록 제거

{
  
"to": "device token list",
  "data": {
    "body": "Body of Your Notification in Data",
    "title": "Title of Your Notification in Title",
    "key_1": "Value for key_1",
    "image_url": "www.abc.com/xyz.jpeg",
    "key_2": "Value for key_2"
  }
}

메시지 수신 시 호출 솔루션()

  1. 앱 포그라운드:

OnMessage Received(RemoteMessage remoteMessage)가 호출되면 알림 표시줄에 LargeIcon 및 BigPicture가 표시됩니다.알림데이터 블록 모두에서 콘텐츠를 읽을 수 있습니다.

  1. 백그라운드에서 앱:

수신된 메시지(RemoteMessage remoteMessage)가 호출되면 알림 키가 응답에 없기 때문에 시스템 트레이가 메시지를 수신하지 않습니다.알림 표시줄에 큰 아이콘 및 큰 그림 표시

코드

 private void sendNotification(Bitmap bitmap,  String title, String 
    message, PendingIntent resultPendingIntent) {

    NotificationCompat.BigPictureStyle style = new NotificationCompat.BigPictureStyle();
    style.bigPicture(bitmap);

    Uri defaultSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

    NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
    String NOTIFICATION_CHANNEL_ID = mContext.getString(R.string.default_notification_channel_id);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "channel_name", NotificationManager.IMPORTANCE_HIGH);

        notificationManager.createNotificationChannel(notificationChannel);
    }
    Bitmap iconLarge = BitmapFactory.decodeResource(mContext.getResources(),
            R.drawable.mdmlogo);
    NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(mContext, NOTIFICATION_CHANNEL_ID)
            .setSmallIcon(R.drawable.mdmlogo)
            .setContentTitle(title)
            .setAutoCancel(true)
            .setSound(defaultSound)
            .setContentText(message)
            .setContentIntent(resultPendingIntent)
            .setStyle(style)
            .setLargeIcon(iconLarge)
            .setWhen(System.currentTimeMillis())
            .setPriority(Notification.PRIORITY_MAX)
            .setChannelId(NOTIFICATION_CHANNEL_ID);


    notificationManager.notify(1, notificationBuilder.build());


}

참조 링크:

https://firebase.google.com/docs/cloud-messaging/android/receive

앱이 백그라운드 모드이거나 비활성(죽음) 상태인 경우 알림클릭하면 LaunchScreen(나의 경우 실행 화면은 MainActivity.java)에서 페이로드를 확인해야 합니다.

MainActivity.java추가 작성 확인:

    if (getIntent().getExtras() != null) {
        for (String key : getIntent().getExtras().keySet()) {
            Object value = getIntent().getExtras().get(key);
            Log.d("MainActivity: ", "Key: " + key + " Value: " + value);
        }
    }

저도 같은 문제가 생겼어요.앱이 포그라운드인 경우 - 알림 유형에 따라 데이터베이스를 업데이트할 수 있는 백그라운드 서비스를 트리거합니다.그러나 앱은 백그라운드로 이동합니다. 기본 알림 서비스는 사용자에게 알림을 표시하도록 주의를 기울입니다.

여기 백그라운드에서 앱을 식별하고 백그라운드 서비스를 시작하는 제 솔루션이 있습니다.

public class FirebaseBackgroundService extends WakefulBroadcastReceiver {

  private static final String TAG = "FirebaseService";

  @Override
  public void onReceive(Context context, Intent intent) {
    Log.d(TAG, "I'm in!!!");

    if (intent.getExtras() != null) {
      for (String key : intent.getExtras().keySet()) {
        Object value = intent.getExtras().get(key);
        Log.e("FirebaseDataReceiver", "Key: " + key + " Value: " + value);
        if(key.equalsIgnoreCase("gcm.notification.body") && value != null) {
          Bundle bundle = new Bundle();
          Intent backgroundIntent = new Intent(context, BackgroundSyncJobService.class);
          bundle.putString("push_message", value + "");
          backgroundIntent.putExtras(bundle);
          context.startService(backgroundIntent);
        }
      }
    }
  }
}

manifest.xml에서

<receiver android:exported="true" android:name=".FirebaseBackgroundService" android:permission="com.google.android.c2dm.permission.SEND">
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            </intent-filter>
        </receiver>

최신 Android 8.0 버전에서 이 솔루션을 테스트했습니다.감사해요.

를 합니다.handleIntentFirebaseMessageService저한테는 효과가 있어요.

여기에 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);
    }
}

그리고 그것은 자바의 코드입니다.

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

기본적으로 앱이 백그라운드에서 실행되고 알림을 클릭하면 앱의 Launcher Activity가 실행됩니다. 알림과 함께 데이터 부분이 있는 경우 다음과 같은 작업으로 처리할 수 있습니다.

if(getIntent().getExtras()! = null){
  //do your stuff
}else{
  //do that you normally do
}

답변이 많이 늦어질 수도 있지만 공식 문서가 좀 헷갈립니다.

또한 두 가지 유형의 알림이 있음이 분명합니다.

  • 알림 메시지:FCM에 의해 자동 처리됨
  • 데이터 메시지:클라이언트 앱에서 처리됩니다.

서버가 데이터 메시지를 보낸다면 의심할 여지 없이 onMessageReceived() 메서드가 호출되지만 MessageReceived() 메서드의 Notification 메시지의 경우 앱이 포그라운드에 있고 앱이 백그라운드에 있을 때만 우리가 보내는 데이터가 null일 때만 호출됩니다.

예:

서버가 알림 메시지 유형을 보내고 있다고 가정합니다.

A. 포그라운드의 경우:

  • remoteMessage.data["key"]가 작동합니다.

B. 백그라운드의 경우: -remoteMessage.data["key"]는 null을 반환하지만 getIntent().getExtras().getString("key")이 있는 기본 작업에서 동일한 의도 데이터를 찾으면 여기서 작동합니다.

C. kill의 경우: -remoteMessage.data["key"]는 null을 반환하지만 getIntent().getExtras().getString("key")과 함께 기본 작업에서 동일한 의도 데이터를 찾으면 여기서 작동합니다.

이제 서버가 데이터 메시지 유형을 전송하고 있다고 가정하겠습니다.

D. 포그라운드의 경우:

  • remoteMessage.data["key"]가 작동합니다.

E. 배경이 있는 경우:

  • remoteMessage.data["key"]가 작동합니다.

F. 살인의 경우:

  • remoteMessage.data["key"]가 작동합니다.

MessageReceived() 메서드에서 데이터 메시지가 항상 호출되지만 알림 메시지와 앱이 백그라운드/킬 상태인 경우 B 솔루션을 사용할 수 있습니다.감사해요.

저는 그것이 모두의 시간을 절약하기를 바랍니다.

t3h Exi의 솔루션에 따르면 여기에 클린 코드를 게시하고 싶습니다.My Firebase Messaging Service에 넣기만 하면 앱이 백그라운드 모드에 있으면 모든 것이 정상적으로 작동합니다.적어도 com.google을 컴파일해야 합니다.화재 기지:화재 기지:10.2.1

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

앱이 백그라운드에 있는 경우 기본적으로 Fire-base 알림을 처리하지만 사용자 지정 알림을 원할 경우 사용자 지정 데이터(데이터 페이로드)를 전송하는 서버 측을 변경해야 합니다.

서버 요청에서 알림 페이로드를 완전히 제거합니다.데이터만 전송하고 수신된 메시지()에서 처리합니다. 그렇지 않으면 앱이 백그라운드에 있거나 삭제되었을 때 수신된 메시지가 트리거되지 않습니다.

서버 사이드 코드 형식은 다음과 같습니다.

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

참고: 위 코드의 이 행을 참조하십시오.
" in Exchange의 Data "대신 " 매개 를 사용해야 합니다."text": "Data payload "John Doe" "John Doe" "Message"는 "body" 메시지입니다

받은 메시지에()

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

저도 비슷한 문제가 있었어요.이 페이지에 언급된 답변과 참고 자료를 바탕으로 다음과 같은 접근 방식으로 문제를 해결한 방법에 대한 저의 의견을 제시합니다.

제가 이전에 가지고 있던 메시지 형식은 다음과 같습니다.

    {
  "notification": {
    "title": "AppName",
    "sound": null,
    "body": "Hey!YouhaveaMessage"
  },
  "data": {
    "param1": null,
    "param2": [
      238
    ],
    "id": 1
  },
  "to": "--the device push token here--"
}

메시지 형식을 아래와 같이 수정했습니다.

    {
  "data": {
    "title": "AppName",
    "body": "Hey! You have a message",
    "param1": null,
    "param2": [
      238
    ],
    "id": 1
  },
  "priority": "high",
  "to": " — device push token here — "
}

그런 다음 "데이터" 페이로드 자체에서 제목, 본문 및 모든 매개 변수를 검색했습니다.이를 통해 문제가 해결되었고 앱이 백그라운드에 있더라도 OnMessage Received 콜백을 받을 수 있었습니다.같은 문제를 설명하는 블로그 글을 썼는데, 여기서 찾을 수 있습니다.

{
      "notification": {
        "title": "Notification Title",
        "body": "Notification Body",
        "click_action": "ActivityToOpen"
      },
      "data": {
        "key": "value "
      },
      "to": "id"
}

FCM 페이로드에 위와 같은 알림 {} 블록이 있고 앱이 백그라운드에 있으면 시스템은 알림 {}에 지정된 제목과 본문으로 알림을 빌드합니다.사용자가 클릭하면 click_action에 언급된 작업이 열립니다. 아무것도 지정되지 않은 경우 기본 시작 프로그램 작업이 열리고 데이터 {} 블록 내의 데이터에 액세스할 수 있습니다.

intent.extras // of the launcher activity

앱이 포그라운드에 있으면 Firebase MessagingService() 클래스의 MessageReceived()에 있는 함수가 트리거됩니다.알림을 직접 작성해야 하며 다음과 같이 데이터에 액세스할 수 있습니다.

val value = message.data.getOrDefault("key", "")

FCM 페이로드가 다음과 같이 알림 블록 {}이(가) 없는 경우;

{ 
    "data": {
    "title": "Notification Title",
     "body": "Notification Body",
    "key": "value "
    },
  "to" : "id"
} 

FirebaseMessagingService() 클래스의 MessageReceived() 함수는 앱이 백그라운드 또는 포그라운드에 있는지 여부에 관계없이 트리거되므로 알림을 직접 빌드해야 합니다.

다음과 같이 데이터에 액세스할 수 있습니다.

    override fun onMessageReceived(message: RemoteMessage) {
        super.onMessageReceived(message)
        val title = message.data.getOrDefault("title", "")
        val body = message.data.getOrDefault("body", "")
}

메시지 유형을 데이터로 변경한다는 답변은 명확하다고 생각합니다.

그러나 수신한 메시지 유형을 결정할 수 없는 경우 처리해야 하는 경우가 있습니다.제 방법을 여기에 올립니다.방금 Firebase Messaging Service를 구현하고 handlIntent() 메서드로 메시지를 처리했습니다.여기서 자신의 알림을 사용자 지정할 수 있습니다.sendYourNotificatoin()을 사용하여 자신만의 방법을 구현할 수 있습니다.

class FCMPushService : FirebaseMessagingService() {

companion object {
    private val TAG = "FCMPush"
}



override fun handleIntent(intent: Intent?) {
    Logger.t(TAG).i("handleIntent:${intent.toString()}")
    val data = intent?.extras as Bundle
    val remoteMessage = RemoteMessage(data)

    if (remoteMessage.data.isNotEmpty()) {
        val groupId: String = remoteMessage.data[MESSAGE_KEY_GROUP_ID] ?: ""
        val title = remoteMessage.notification?.title ?: ""
        val body =  remoteMessage.notification?.body ?: ""
        if (title.isNotEmpty() && body.isNotEmpty())
            sendYourNotificatoin(this, title, body, groupId)
    }
}

}

기본 활동의 작성 방법에서 이를 호출합니다.

if (getIntent().getExtras() != null) {
           // Call your NotificationActivity here..
            Intent intent = new Intent(MainActivity.this, NotificationActivity.class);
            startActivity(intent);
        }

사용해 보십시오.

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

행운

이 문제가 발생했습니다(앱이 백그라운드에 있거나 닫혔을 경우 알림 클릭 시 앱이 열리지 않음). 문제는 유효하지 않습니다.click_action알림 본문에서 제거하거나 유효한 항목으로 변경해 보십시오.

강조할 만한 점은 앱이 백그라운드에 있을 때도 호출된 MessageReceived 핸들러에 접속하려면 데이터 메시지(데이터 키만 해당)를 사용해야 한다는 것입니다.페이로드에 다른 알림 메시지 키가 있으면 안 됩니다. 그렇지 않으면 앱이 백그라운드에 있을 때 핸들러가 트리거되지 않습니다.

여기에 언급되어 있습니다(FCM 설명서에서는 그렇게 강조되지 않았습니다).

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

앱 서버 및 FCM 서버 API 사용:데이터 키만 설정합니다.접을 수도 있고 접을 수도 없습니다.

현재 사용 중인 백엔드는 데이터 메시지가 아닌 알림 메시지를 사용하고 있습니다.그래서 모든 답을 읽은 후에 저는 시작된 활동에 대한 의도의 묶음에서 여분의 것을 찾으려고 노력했습니다.하지만 내가 어떤 열쇠에서 찾으려 했든 간에getIntent().getExtras();값이 항상 null이었습니다.

하지만, 저는 마침내 알림 메시지를 사용하여 데이터를 보내고 의도에서 데이터를 검색할 수 있는 방법을 찾았습니다.

여기서 핵심은 알림 메시지에 데이터 페이로드를 추가하는 것입니다.

예:

{
    "data": {
        "message": "message_body",
        "title": "message_title"
    },
    "notification": {
        "body": "test body",
        "title": "test title"
    },
    "to": "E4An.."
}

이렇게 하면 다음과 같은 방법으로 정보를 얻을 수 있습니다.

intent.getExtras().getString("title")▁▁be 될 것입니다.message_title

그리고.intent.getExtras().getString("message")▁▁be 될 것입니다.message_body

언급

문제가 빅 이미지를 표시하는 것과 관련된 경우, 즉 파이어베이스 콘솔에서 이미지와 함께 푸시 알림을 보내고 앱이 전경에 있는 경우에만 이미지를 표시하는 경우.이 문제에 대한 해결책은 데이터 필드로만 푸시 메시지를 보내는 것입니다.이와 같은 것:

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

메시지가 수신되고 앱이 백그라운드에 있을 때 알림이 기본 활동의 추가 의도로 전송됩니다.

기본 활동의 oncreate() 또는 resume() 기능에서 추가 값을 확인할 수 있습니다.

데이터, 테이블 등의 필드(알림에 지정된 필드)를 확인할 수 있습니다.

예를 들어 데이터를 키로 사용하여 보냈습니다.

public void onResume(){
    super.onResume();
    if (getIntent().getStringExtra("data")!=null){
            fromnotification=true;
            Intent i = new Intent(MainActivity.this, Activity2.class);
            i.putExtra("notification","notification");
            startActivity(i);
        }

}

Firebase Messaging Service에 다음이 있습니다.

public void handleIntent(Intent intent) {
    String action = intent.getAction();
    if (!"com.google.android.c2dm.intent.RECEIVE".equals(action) && !"com.google.firebase.messaging.RECEIVE_DIRECT_BOOT".equals(action)) {
        if ("com.google.firebase.messaging.NEW_TOKEN".equals(action)) {
            this.onNewToken(intent.getStringExtra("token"));
        } else {
            Log.d("FirebaseMessaging", "Unknown intent action: " + intent.getAction());
        }
    } else {
        this.handleMessageIntent(intent);
    }

}

Firebase Messaging Service를 확장하는 자체 서비스 클래스에서 이 기능을 재정의할 수 있습니다.

this.handleMessageIntent(의도); -> 앱이 닫혔을 때 알림을 처리합니다.이 줄을 제거하고 MessageReceived() 메서드에서 재정의에 사용되는 함수를 사용하여 사용자 지정 레이아웃을 표시할 수 있습니다.배경/포그라운드 모두에서 사용자 지정 레이아웃을 표시할 수 있습니다.

저도 같은 문제를 겪고 있었고 이것에 대해 좀 더 조사했습니다.앱이 백그라운드에 있을 때 알림 메시지는 시스템 트레이로 전송되지만 데이터 메시지는 다음으로 전송됩니다.onMessageReceived()
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.java .

보내는 메시지를 확인하기 위해 문서에는 "앱 서버FCM 서버 API 사용: 데이터 키만 설정합니다. 접을 수도 있고 접을 수도 없습니다."
https://firebase.google.com/docs/cloud-messaging/concept-options#notifications_and_data_messages 을 참조하십시오.

메시지에는 알림 메시지와 데이터 메시지의 두 가지 유형이 있습니다.데이터 메시지만 보내는 경우 메시지 문자열에 알림 개체가 없습니다.앱이 백그라운드에 있을 때 호출됩니다.

@Mahesh Kavathya의 답을 확인합니다.나의 경우, 서버 코드는 다음과 같습니다.

{
"notification": {
  "body": "here is body",
  "title": "Title",
 },
 "to": "sdfjsdfonsdofoiewj9230idsjkfmnkdsfm"
}

다음으로 변경해야 합니다.

{
 "data": {
  "body": "here is body",
  "title": "Title",
  "click_action": "YOUR_ACTION"
 },
"notification": {
  "body": "here is body",
  "title": "Title"
 },
 "to": "sdfjsdfonsdofoiewj9230idsjkfmnkdsfm"
}

그런 다음 백그라운드에서 앱을 실행하는 경우 기본 활동 의도 추가가 "데이터"를 가져옵니다.

행운을 빕니다.

이것이 의도된 동작입니다. 백그라운드에서 데이터를 수신하려면 firebase 알림 데이터 집합에 click_action을 설정해야 합니다.

여기에서 업데이트된 답변을 참조하십시오. https://stackoverflow.com/a/73724040/7904082

Firebase 푸시 알림에는 두 가지 유형이 있습니다.

1 - 알림 메시지(메시지 표시) -> -- 1.1 이 변형을 선택하면 앱이 백그라운드에 있으면 OS가 자체 알림을 생성하여 데이터를 전달합니다.intent그러면 이 데이터를 처리하는 것은 고객에게 달려 있습니다.

1.2 앱이 포그라운드에 있는 경우 알림은 다음을 통해 수신됩니다.callback-function에 시대에FirebaseMessagingService그리고 그것을 다루는 것은 고객에게 달려 있습니다.

- messages (data) -만 (되며, 2 - 를 통해 모두 입니다.FirebaseMessagingService

공식 문서에 따르면 다음과 같습니다. https://firebase.google.com/docs/cloud-messaging/concept-options

언급URL : https://stackoverflow.com/questions/37358462/firebase-onmessagereceived-not-called-when-app-in-background

반응형