-
[Android] FCM을 이용해 Push 구현하기Android 2021. 4. 15. 18:38반응형
Push Service? FCM?
서버에서 모바일 장치에 보내는 알림 또는 메시지.
직접 구현한 서버에서 사용자 장치로 알림을 보내기 위해서는 앱과 서버의 연결을 지속적으로 유지해야한다.
그러나 FCM(Firebase Cloud Messaging)은 구글 클라우드 서버를 사용해 앱에서 서버에 연결하지 않아도 기기의 내부 연결을 통해 메시지를 보낼 수 있다.
FCM을 사용해서 메시지를 보내는 과정
FCM을 이용해 메시지를 보내는 과정을 간단하게 다섯 단계로 나눠서 정리해보았다.
1. 토큰 요청 및 획득
먼저 사용자가 앱을 설치하고 최초 실행시 토큰을 얻기위해 클라우드 서버에 요청을 보내고 토큰을 획득한다.
2. 서버에 토큰 저장
획득한 토큰을 서버로 전송하여 서버 db에 저장한다.
이 토큰은 서버가 클라우드에 메시지 전송을 요청할 때 어디로 보내는지 구분하기 위한 용도로 사용된다.
3. 토큰을 이용해 메시지 전송 요청
서버에서 클라우드로 메시지 데이터와 함께 토큰을 보내 전송을 요청한다.
4. 메시지 전송
클라우드는 요청받은 메시지를 토큰에 해당하는 단말기에 전송한다.
5. 리스너를 통해 메시지 수신
앱이 실행중이 아니더라도 리스너를 통해 메시지를 수신할 수 있다.
Firebase 페이지에 앱 등록 및 프로젝트 설정
푸시 서비스를 이용하기 위해서는 Firebase에 앱을 등록하고 고유한 key를 받아야 메시지 전송을 요청할 수 있다.
그러면 앱을 등록하는 방법을 알아보자.
먼저 구글 계정에 로그인하고 firebase 홈페이지에서 오른쪽 상단의 [콘솔로 이동] 을 클릭해서 콘솔에 접속한다.
콘솔에서 프로젝트 만들기를 클릭하고, 프로젝트 이름 작성 및 구글 애널리틱스 설정을 한다.
프로젝트가 생성되면 프로젝트로 들어가서 화면 중간의 앱을 추가하여 시작하기에서 Android를 선택한다.
Android 패키지 이름에 앱의 패키지 이름을 작성하고 다음 단계로 넘어간다.
google-services.json을 다운로드 받아 앱 모듈 루트 디렉토리에 넣는다.
안드로이드 스튜디오 프로젝트 영역에서 보기 설정을 Android에서 Project로 변경해서 넣으면 쉽게 찾아서 넣을 수 있다.
그리고 안내에 따라 루트(프로젝트) 수준의 build.gradle에 아래와 같이 google-service 플러그인을 추가한다.
buildscript { repositories { ... } dependencies { ... //이 한줄을 추가하자. classpath 'com.google.gms:google-services:4.3.5' } } allprojects { repositories { ... } }
앱 모듈 수준의 build.gradle에도 플러그인을 추가해주고 sync now를 눌러준다.
plugins { ... } android { ... } dependencies { ... } //가장 밑에 한줄을 추가하자!! apply plugin: 'com.google.gms.google-services'
FCM을 수신할 수 있는 서비스 만들기
기본 설정이 끝났으면 이제 메시지를 받았을 때 수신할 수 있도록 구현해보자.
먼저 앱 모듈 수준의 build.gradle에 Firebase관련 클래스를 사용할 수 있도록 라이브러리를 추가한다.
dependencies { ... implementation 'com.google.firebase:firebase-messaging:21.1.0' }
그리고 FirebaseMessagingService를 상속받는 서비스를 하나 만들고, onNewToken()와 onMessageReceived()를 재정의한다.
public class MyFirebaseMessagingService extends FirebaseMessagingService { @Override public void onNewToken(@NonNull String token) { super.onNewToken(token); //token을 서버로 전송 } @Override public void onMessageReceived(@NonNull RemoteMessage remoteMessage) { super.onMessageReceived(remoteMessage); //수신한 메시지를 처리 } }
onNewToken()은 클라우드 서버에 등록되었을 때 호출되고, 파라미터로 전달된 token이 앱을 구분하기 위한 고유한 키가 된다.
onMessageReceived()는 클라우드 서버에서 메시지를 전송하면 자동으로 호출되고,
해당 메서드안에서 메시지를 처리하여 사용자에게 알림을 보내거나 할 수 있다.
그리고 구현한 서비스를 매니페스트에 등록하고, 메시지를 수신하기 위한 인텐트 필터를 설정해준다.
푸시 서비스는 인터넷을 사용하기 때문에 인터넷 퍼미션도 추가한다.
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.maejin.samplepush"> <!-- INTERNET 퍼미션 추가! --> <uses-permission android:name="android.permission.INTERNET"/> <application ...> <activity android:name=".MainActivity"> ... </activity> <!-- 서비스를 추가하고 인텐트 필터를 설정한다. --> <service android:name=".MyFirebaseMessagingService"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT"/> </intent-filter> </service> </application> </manifest>
등록된 token을 확인하고 싶다면 FirebaseMessaging.getInstance().getToken()를 호출해서 알 수 있다.
String token = FirebaseMessaging.getInstance().getToken().getResult();
아래와 같이 addOnSuccessListener를 등록한다면, 토큰을 확인했을 때 자동으로 onSuccess()를 호출한다.
FirebaseMessaging.getInstance().getToken().addOnSuccessListener(new OnSuccessListener<String>() { @Override public void onSuccess(String token) { //... } });
가장 중요한 메시지를 수신했을 때 어떻게 처리할 수 있는지 알아보자.
먼저 OnMessageReceived의 파라미터인 remoteMessage에 수신된 메시지가 전달된다.
remoteMessage는 getFrom(), getNotification()등의 메서드를 호출해서 메시지에 대한 정보를 얻을 수 있는데,
getNotification()는 getTitle(), getBody()로 타이틀과 내용을 얻을 수 있다.
아래 코드는 메시지 정보를 받아 notification으로 등록하는 코드다.
@Override public void onMessageReceived(@NonNull RemoteMessage remoteMessage) { super.onMessageReceived(remoteMessage); NotificationManagerCompat notificationManager = NotificationManagerCompat.from(getApplicationContext()); NotificationCompat.Builder builder = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (notificationManager.getNotificationChannel(CHANNEL_ID) == null) { NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT); notificationManager.createNotificationChannel(channel); } builder = new NotificationCompat.Builder(getApplicationContext(), CHANNEL_ID); }else { builder = new NotificationCompat.Builder(getApplicationContext()); } String title = remoteMessage.getNotification().getTitle(); String body = remoteMessage.getNotification().getBody(); builder.setContentTitle(title) .setContentText(body) .setSmallIcon(R.drawable.ic_launcher_background); Notification notification = builder.build(); notificationManager.notify(1, notification); }
테스트 하기 - Firebase Console
푸시 서비스를 구현하고 제대로 동작하는지 확인하기 위해 별도의 서버를 구현하지 않아도 된다.
firebase의 콘솔에서 테스트 메시지를 보낼 수 있다.
콘솔 > 프로젝트 선택 > 왼쪽 바에서 참여 > Cloud Messaging으로 이동한다.
그러면 화면 상단에 send your first message를 클릭해 메세지를 보낼 수 있다.
그대로 메세지를 전송하여 테스트할 수도 있다.
그러나 그냥 왼쪽에 테스트 메시지 전송을 눌러 확인한 토큰을 입력하고 전송해보는 것이 간편한듯.
테스트 하기 - Postman (HTTP)
HTTP프로토콜 형식으로 클라우드로 POST 요청을 보내 확인할 수 있다.
터미널이나 다른 툴을 써도 되지만 가장 간편하게 테스트 할 수 있는 Postman을 추천한다.
https://fcm.googleapis.com/fcm/send 에 POST 요청을 보내고,
헤더의 Content-Type은 application/json, Authorization에는 등록한 앱의 서버키를 넣는다.
서버키는 Firebase 콘솔에서 [프로젝트 설정 > 클라우드 메시징] 에서 확인할 수 있다.
getNotification()를 통해 title과 body를 가져온다면 body는 아래와 같은 json형식으로 보내면 된다.
remoteMessage에서 Map 형식으로 데이터를 꺼낼 수 있는 getData()를 쓰기 위해서는 "data"로 객체를 묶어서 작성하면 된다.
테스트앱은 notification보다는 화면으로 보는게 편해서 그냥 TextView에 띄웠다.
아래는 테스트 결과!
'Android' 카테고리의 다른 글
[Android] Compose - Lifecycle 정리 (0) 2024.03.15 [Android] AAC-LiveData의 setValue와 postValue (3) 2021.04.23 [Android] Notification 구현 예제 및 Channel (0) 2021.04.15 [Android] 스레드(Thread)와 핸들러(Handler), 작업 스레드에서 UI 업데이트 요청하기 (2) 2021.04.14 [Android] JSON 라이브러리 : GSON (0) 2021.04.12