플랫폼 개발팀 기술 블로그

[FCM] #4. Android 메시지 처리 본문

Article

[FCM] #4. Android 메시지 처리

피랑이 2019. 2. 22. 11:09

[FCM] #1. 소개 및 메시지

[FCM] #2. Firebase 프로젝트 생성 및 Android 앱 FCM 설정

[FCM] #3. Firebase 메시지 전송

[FCM] #4. Android 메시지 처리


이번에는 Android에서 단순 메시지가 아닌 아이콘이나 이미지 메시지를 어떻게 처리하는지 알아본다. 

우선 안드로이드 관련 코드들은 제외하고, 메시지 관련된 부분만 설명한다. 


푸시 메시지는 FirebaseMessagingService 클래스를 상속받아 onMessageReceived 메소드를 오버라이딩 해서 커스텀하게 처리한다.

onMessageReceived 메소드에서 메시지 알림 처리를 하면 앱이 포그라운드, 백그라운드 상관없이 푸시 메시지가 도착한다. 

코드 관련 정보는 #2. Firebase 프로젝트 생성 및 Android 앱 FCM 설정 부분에 있다.

@Override public void onMessageReceived(RemoteMessage remoteMessage) { // ... // TODO(developer): Handle FCM messages here. // Not getting messages here? See why this may be: https://goo.gl/39bRNJ Log.d(TAG, "From: " + remoteMessage.getFrom()); // Check if message contains a data payload. if (remoteMessage.getData().size() > 0) { Log.d(TAG, "Message data payload: " + remoteMessage.getData()); if (/* Check if data needs to be processed by long running job */ true) { // For long-running tasks (10 seconds or more) use Firebase Job Dispatcher. scheduleJob(); } else { // Handle message within 10 seconds handleNow(); } } // Check if message contains a notification payload. if (remoteMessage.getNotification() != null) { Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody()); } // Also if you intend on generating your own notifications as a result of a received FCM // message, here is where that should be initiated. See sendNotification method below. }

푸시 메시지 중 큰 아이콘 메시지, 이미지 메시지 등은 onMessageReceived 메서드에서 처리한다.

remoteMessage는 송신자 정보와 데이터 메시지 정보를 가지고 있다. 

보통 데이터 메시지 안에 제목, 내용, 이미지 정보등을 포함하여 맞춤형 알림 처리를 한다.


이전 HTTP API 기준으로 아이콘 메시지, 이미지 메시지 처리를 해보자.


아이콘 메시지

메시지 정보

아래는 FCM 접속 서버에 발송하는 데이터 메시지 정보이다.

여기서 데이터 메시지는 커스텀하게 key,value를 설정할 수 있다. [FCM] #1. 소개 및 메시지 참고

{
  "data":
    {
      "title":"😃제목😃",
      "body":"😃내용😃",
      "largeIcon":"https://t1.daumcdn.net/news/201902/13/ZDNetKorea/20190213133354225nmeh.jpg"
  },
  "to":"사용자 토큰"
}

onMessageReceived 

Oreo 버전 이상부터는 NotificationChannel 정보를 추가해준다. (추가하지 않으면 메시지 수신 안함)
largeIcon에 링크가 아닌 데이터 자체 정보를 데이터 메시지에 넣을 수 있으나 FCM 전체 페이로드가 4KB까지 지원하므로 권장하지는 않는다. (이미지 메시지도 마찬가지...)

private void onMessageReceived(RemoteMessage remoteMessage){
        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 , intent,
                PendingIntent.FLAG_ONE_SHOT);

        String channelId = "one-channel";
        String channelName = "My Channel One1";
        String channelDescription = "My Channel One Description";
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            NotificationChannel notificationChannel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_DEFAULT);
            notificationChannel.setDescription("channel description");
            notificationChannel.enableLights(true);
            notificationChannel.setLightColor(Color.GREEN);
            notificationChannel.enableVibration(true);
            notificationChannel.setVibrationPattern(new long[]{100, 200, 100, 200});
            notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
            notificationManager.createNotificationChannel(notificationChannel);
        }

        Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channelId)
                .setSmallIcon(R.mipmap.ic_launcher)
                 //제목
                .setContentTitle(remoteMessage.getData().get("title"))
                 //내용
                .setContentText(remoteMessage.getData().get("body"))
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);

        try {
            URL url = new URL(remoteMessage.getData().get("largeIcon"));
            //아이콘 처리 
            bigIcon = BitmapFactory.decodeStream(url.openConnection().getInputStream());
            notificationBuilder.setLargeIcon(bigIcon);
        } catch (IOException e) {
            e.printStackTrace();
        }

        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        notificationManager.notify(333 /* ID of notification */, notificationBuilder.build());
    }

결과

이미지 메시지

메시지 정보

이미지 정보도 아이콘과 동일한 이미지로 테스트 해본다. 
{
  "data":
    {
      "title":"😃제목😃",
      "body":"😃내용😃",
      "imgUrl":"https://t1.daumcdn.net/news/201902/13/ZDNetKorea/20190213133354225nmeh.jpg"
  },
  "to":"사용자 토큰"
}

onMessageReceived 

푸시 메시지에 이미지를 적용하기 위해서는 setStyle()에 NotificationCompat.BigPictureStyle() 을 넣어서 사용한다. 
수신된 이미지 메시지는 펼쳐진 상태와 줄여진 상태에서 제목과 내용을 표현하는 방법이 다르다. 

펼쳐진 상태


 제목

 NotificationCompat.Builder.setContentTitle()

 내용

 NotificationCompat.Builder.setContentText()

 줄여진 상태


 제목

 NotificationCompat.BigPictureStyle().setBigContentTitle()

 내용

 NotificationCompat.BigPictureStyle()..setSummaryText()

private void onMessageReceived(RemoteMessage remoteMessage){
        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 , intent,
                PendingIntent.FLAG_ONE_SHOT);

        String channelId = "one-channel";
        String channelName = "My Channel One1";
        String channelDescription = "My Channel One Description";
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            NotificationChannel notificationChannel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_DEFAULT);
            notificationChannel.setDescription("channel description");
            notificationChannel.enableLights(true);
            notificationChannel.setLightColor(Color.GREEN);
            notificationChannel.enableVibration(true);
            notificationChannel.setVibrationPattern(new long[]{100, 200, 100, 200});
            notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
            notificationManager.createNotificationChannel(notificationChannel);
        }

        Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channelId)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle(remoteMessage.getData().get("title"))
                .setContentText(remoteMessage.getData().get("body"))
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);

        try {
            URL url = new URL(remoteMessage.getData().get("imgUrl"));
            //이미지 처리 
            bigPicture = BitmapFactory.decodeStream(url.openConnection().getInputStream());
            notificationBuilder.setStyle(
                    new NotificationCompat.BigPictureStyle()
                            .bigPicture(bigPicture)
                            .setBigContentTitle(remoteMessage.getData().get("title"))
                            .setSummaryText(remoteMessage.getData().get("body")));
        } catch (IOException e) {
            e.printStackTrace();
        }

        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        notificationManager.notify(333 /* ID of notification */, notificationBuilder.build());
    }

결과



아이콘과 이미지를 같이 처리하면 아래와 같은 결과를 얻을 수 있다. 


마치며

지금까지 푸시 메시지 발신, 수신을 확인하기 위해서 Firebase 프로젝스 생성 및 설정, AndroidStudio로 앱 생성 및 설정 작업, 메시지 전송 작업을 하였다. 
푸시 메시지에 수신 처리은 그렇게 어렵지 않다. 
사용자에게 메시지를 어떻게 발송할지에 대한 니즈에 따라 메시지를 발송하는 담당하는 앱서버에서 작업이 달라진다. 
(대량 메시지 발송, 특정 앱의 키워드에 대한 알림 수신, 주문을 했을 때 주문 및 배송상태에 대한 수신, 게임 설치 중이나 설치 완료에 대한 수신 등등)



Comments