ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Android FCM 구현하기(GCM에서 전환) - 2/2 소스구현
    Android 2019. 4. 1. 16:12

     

     

    1. build.gradle 세팅

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    buildscript {
         dependencies {
             classpath 'com.google.gms:google-services:4.0.1'
         }
    }
     
     
    dependencies {
    }
     
    Colored by Color Scripter

     

     

     

     

    2. AndroidManifest.xml 세팅

    1
    2
    3
    4
    5
    6
    7
     
    <service android:name=".FCM.MyFcmListenerService">
         <intent-filter>
             <action android:name="com.google.firebase.MESSAGING_EVENT"/>
         </intent-filter>
    </service>
     
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/>
     

     

     

     

     

    3. Push Type 3가지 ( Notification / Data / Notification+Data )

     

    - FCM으로 넘어 오면서 주의할 부분이 있다. 앱이 백그라운드에 들어가있을때의 onMessageReceived()의 호출 유무이다.

    FCM 콘솔에서 테스트를 하려고 푸쉬를 쏘면 앱이 백그라운드로 들어가있을때 푸쉬정보에 들어가있는 Title과 Message가 자동으로 세팅이되어 푸쉬가 생성되고 커스텀마이징한 onMessageReceived 메소드를 타질 않는다.

     

    푸쉬의 종류에는 3가지로 나눌 수 있다. Notification / Data / Notification+Data 3가지 푸쉬를 나눠서 어떻게 처리되는지 보자.

     

     

    첫번째. Notification 타입

    FCM 콘솔 화면에서 푸쉬를 보낼 수 있는데 notification 항목에 제목과 내용을 담을 수 있다. 아래 항목을 채워서 푸쉬를 보내면 아래와 같은 Json형식으로 푸쉬가 날라온다.

     

    1
    2
    3
    4
    5
    6
    7
    {
         "to" : "token value",
        
    "notification" : {
            "body" : "Message",
           "title" : "Title",
         }
      }

     

     

    두번째. Data 타입

    역시 마찬가지로 FCM 콘솔에서 맨아래 항목이 Data부분을 넣어주는 부분이다. Custom data 부분에 key, value를 채워 보내면된다. 값을 입력하면 여러개를 더 입력할수있게끔 늘어난다. 또한 Value에는 String 뿐만 아니라 Json형식으로도 입력이 가능하다.

     

    그런데, FCM콘솔에서는 Notification입력하는 부분에 body부분이 필수 입력으로 되어있어 Data부분만 입력해서 푸쉬를 날릴수는 없다. 서버를 직접 구현해야 Data타입으로 푸쉬 송신이 가능하다.

     

    1
    2
    3
    4
    5
    6
    7
    8
    {
        "to" : "token value",
     
        "data" : {
          "name" : "JSLEE",
          "body" : "Message",
          "title" : "Title"
        }
    }

     

     

    세번째. Notification + Data 타입

    Notification항목과 Data항목이 모두 들어가 있는 푸쉬타입이다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    {
      "to" : "token value",
     
    "notification" : {
           "body" : "Message",
            "title" : "Title",
        },
     
    "data" : {
            "name" : "JSLEE",
           "body" : "Message",
           "title" : "Title"
        }
    }

     

     

    이렇게 3가지 푸쉬를 나눠서 설명하는데에는 이유가 있다. 바로 푸쉬 종류에 따라서 onMessageReceived() 메소드 호출 유무가 달라지기 때문이다.

     

    Notification 타입

    - 포그라운드 : onMessageReceived() 메소드를 타며 커스텀마이징 한대로 작동한다.

    - 백그라운드 : Notificaition의 title과 body 항목대로 푸쉬를 자동으로 만들며 터치시 기본적으로 앱을 구동시킨다.

     

    Data 타입

    - 포그라운드 : onMessageReceived() 메소드를 타며 커스텀마이징 한대로 작동한다.

    - 백그라운드 : onMessageReceived() 메소드를 타며 커스텀마이징 한대로 작동한다.

     

    Notification + Data 타입

    - 포그라운드 : onMessageReceived() 메소드를 타며 커스텀마이징 한대로 작동한다.

    - 백그라운드 : Notificaition의 title과 body 항목대로 푸쉬를 자동으로 만들며 터치시 기본적으로 앱을 구동시키며 data 항목은 시작 Activity에 서 extras intent로 extras.getString("key")으로 추출하여 사용할 수 있다.

     

    포그라운드와 백그라운드 모두 동일하게 onMessageReceived를 통해 개발자가 원하는대로 컨트롤 하려면 Data타입의 푸쉬를 사용하는것이 좋다.

     

     

     

     

     

     

    4-1. MyFcmListenerService.java ( onNewToken() )

     

    - 푸쉬 송신에 필요한 Token을 발급 받는다. SharedPreference를 통해 값을 저장하거나 서버통신을 통해 값을 보내거나 하면된다.

    그리고 이전 GCM 과 다른점이 있다. 이전 GCM에서는 메소드가 호출될때마다 계속 토큰이 발급이 되었지만 FCM에서는 최초설치시 한번 발급되고나서 onNewToken이 불려지지 않는다. 최초 설치시 발급되는 토큰값을 바로 저장할 필요가 있다.

    1
    2
    3
    4
     
    @Override
     public void onNewToken(String s){
          String newToken = s;
     }
     
    Colored by Color Scripter

     

     

    혹여나 앱 구동시 마다 토큰 발급이 계속 필요하다고 하면 MainActivity에 아래 메소드를 추가해주면 된다.

    1
    2
    3
    4
    5
    6
     
    FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener( MainActivity.this,  new OnSuccessListener<InstanceIdResult>() {
        @Override
        public void onSuccess(InstanceIdResult instanceIdResult) {
            String newToken = instanceIdResult.getToken();
        }
    });
     
    Colored by Color Scripter

     

     

     

     

     

    4-2. MyFcmListenerService.java ( onMessageReceived() )

    - 푸쉬를 받아서 데이터를 뽑아내는 작업을 한다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    @Override
        public void onMessageReceived(RemoteMessage remoteMessage) {
     
            String message = "";
            String title = "";
     
            // Notifition 항목이 있을때.
            if (remoteMessage.getNotification() != null) {
                message = remoteMessage.getNotification().getBody();
                title = remoteMessage.getNotification().getTitle();
            }
     
            // Data 항목이 있을때.
            Map<StringString> data = remoteMessage.getData();
            String messageData = data.get("message");
            String titleData = data.get("title");
            String nameData = data.get("name");
     
            //저는 포그라운드 백그라운드 동일하게 컨트롤하기 위해 Data항목에 푸쉬 Title, Body 모두 넣어서 구현하였습니다.
            sendNotification(titleData, messageData, nameData);
     
        }
     
    Colored by Color Scripter

     

     

     

     

     

    4-3. MyFcmListenerService.java ( sendNotification() )

    - 뽑아낸 데이터를 기반으로 푸쉬 노티를 생성하는 메소드

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
     private void sendNotification(String title, String message, String name) {
     
            Intent intent;
            PendingIntent pendingIntent;
     
            intent = new Intent(this, MainActivity.class);
            intent.putExtra("name", name);  //push 정보중 name 값을 mainActivity로 넘김
     
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            pendingIntent = PendingIntent.getActivity(this0 /* Request code */, intent, PendingIntent.FLAG_ONE_SHOT);
     
     
            Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
     
            NotificationCompat.Builder notificationBuilder;
            NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
     
            //SDK26부터 푸쉬에 채널항목에 대한 세팅이 필요하다.
            if (Build.VERSION.SDK_INT >= 26) {
     
                String channelId = "test push";
                String channelName = "test Push Message";
                String channelDescription = "New test Information";
                NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_DEFAULT);
                channel.setDescription(channelDescription);
                //각종 채널에 대한 설정
                channel.enableLights(true);
                channel.setLightColor(Color.RED);
                channel.enableVibration(true);
                channel.setVibrationPattern(new long[]{100200300});
                notificationManager.createNotificationChannel(channel);
                //channel이 등록된 builder
                notificationBuilder = new NotificationCompat.Builder(this, channelId);
            } else {
                notificationBuilder = new NotificationCompat.Builder(this);
            }
     
            notificationBuilder.setSmallIcon(R.drawable.ic_stat_ic_notification)
                    .setContentTitle(title)
                    .setStyle(new NotificationCompat.BigTextStyle().bigText(message))
                    .setAutoCancel(true)
                    .setSound(defaultSoundUri)
                    .setContentIntent(pendingIntent)
                    .setContentText(message);
     
             int localTime = new TimeUtil().getuniqTime();
             notificationManager.notify(localTime /* ID of notification */notificationBuilder.build());
        }
     
    Colored by Color Scripter

     

     

     

    댓글

Designed by Tistory.