안드로이드 Firebase FCM

이영준·2023년 4월 20일
0

📌 FCM 주요기능

FCM == Firebase Cloud Messaging
무료로 안정적으로 메시지를 전송하는 교차 플랫폼 메시징 솔루션

  • 알림 메시지 또는 데이터 메시지 전송
  • 다양한 메시지 타겟팅
  • 클라이언트 앱에서 메시지 전송

📌 FCM 구현 경로와 아키텍쳐

1.FCM SDK 설정

  • 플랫폼에 맞는 설정 안내에 따라 앱에서 FCM 설정

2.클라이언트 앱 개발

  • 클라이언트 앱에 메시지 처리, 주제 구독 로직 또는 기타 선택사항 기능을 추가
  • 개발 중에는 테스트 메시지 전송 가능

3.앱 서버 개발

  • 인증, 보내기 요청 작성, 응답 처리등을 수행하는 전송 로직 구축


서버의 역할은 1에서 신뢰할 수 있는 환경으로 파이어베이스로 데이터를 전달해주는 것 2부터는 FCM이 알아서 디바이스로 보내줄 것
안드로이드의 역할은 전송받는 데이터를 잘 받는 것

🔑 FCM 생명주기

  1. FCM에서 메시지를 수신하도록 기기를 등록
  2. 다운스트림 메시지 전송 및 수신

🔑 FCM 메시지 유형

  1. 알림 메시지 : FCM SDK에서 자동처리하여 사용자 기기에 메시지 표시
  • title, body라는 정해진 이름으로 notification을 보냄
  1. 데이터 메시지 : 클라이언트 앱에서 처리
  • 커스텀 키-값 쌍으로 적절한 키를 설정해 클라이언트로 데이터 페이로드 전송. 커스텀으로 data 안의 값을 지정

  1. 데이터 페이로드가 포함된 알림 메시지
    1,2를 둘다 포함하여 수신하는 경우로, 백그라운드/포그라운드 여부에 따라 달라진다.
  • 백그라운드 : 알림 페이로드는 처리되고, 사용자가 알림 탭해야 데이터 페이로드 처리
  • 포그라운드 : 앱에서 페이로드가 둘다 제공되는 메시지 객체 수신

📌 FCM 메시지 SDK 수신

기존의 google-services관련 의존성과 함께

implementation 'com.google.firebase:firebase-messaging-ktx'

를 추가해준다.
https://firebase.google.com/docs/android/setup?hl=ko

🔑 manifest 수정

인터넷 및 FirebaseMessagingService를확장하는 서비스를 추가해야 한다.
백그라운드로 앱이 내려갔을 때 수신받기 위해 서비스가 필요하기 때문이다.

<uses-permission android:name="android.permission.INTERNET" />
...
<service
    android:name=".java.MyFirebaseMessagingService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

https://firebase.google.com/docs/cloud-messaging/android/client?hl=ko

🔑 액티비티에서 토큰 발급

create될 때 파이어베이스 토큰이 있으면 가져오려고 한다. 이 토큰은 앱이 가지고 있는 토큰이다.

FirebaseMessaging.getInstance().token.addOnCompleteListener(OnCompleteListener { task ->
    if (!task.isSuccessful) {
        Log.w(TAG, "Fetching FCM registration token failed", task.exception)
        return@OnCompleteListener
    }

    // Get new FCM registration token
    val token = task.result

    // Log and toast
    val msg = getString(R.string.msg_token_fmt, token)
    Log.d(TAG, msg)
    Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
})

🔑 서비스 구현

서비스에서 토큰 재발급시 전송할 토큰에 대한 서비스 구현

class MyFirebaseMessageService : FirebaseMessagingService() {
    // 새로운 토큰이 생성될 때 마다 해당 콜백이 호출된다.
    override fun onNewToken(token: String) {
        super.onNewToken(token)
        Log.d(TAG, "onNewToken: $token")
        // 새로운 토큰 수신 시 서버로 전송
        MainActivity.uploadToken(token)
    }

    // Foreground에서 Push Service를 받기 위해 Notification 설정
    override fun onMessageReceived(remoteMessage: RemoteMessage) {
    }

}

FirebaseMessagingService의 onNewToken을 구현한다


실행 시 위 처럼 토큰을 발급받아온다.

🔑 메시지 만들기

firebase 메시지에서

메시지를 만들기


발급받은 토큰을 여기에 입력을 하고 테스트를 하면

서비스의 onMessageReceived에서 발급받은 remotemessage 로그를 볼 수 있다.
onMessageReceived: com.google.firebase.messaging.RemoteMessage@f200a5f

재미있는 점은 앱이 백그라운드 상태에 있을 때 똑같이 테스트를 해보면

notification이 와있다. 백그라운드일 때 시스템에서 자동으로 푸쉬 메시지를 보내주는 것이다.

🔑 포그라운드에서도 메시지 notification 띄우기

    override fun onMessageReceived(remoteMessage: RemoteMessage) {

        Log.d(TAG, "onMessageReceived: $remoteMessage")
        remoteMessage.notification?.apply {
            val intent = Intent(this@MyFirebaseMessageService, MainActivity::class.java).apply{
                flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
            }
            val pendingIntent = PendingIntent.getActivity(this@MyFirebaseMessageService, 0, intent, PendingIntent.FLAG_IMMUTABLE)
            val builder = NotificationCompat.Builder(this@MyFirebaseMessageService, MainActivity.channel_id)
                .setSmallIcon(android.R.drawable.ic_dialog_info)
                .setContentTitle(title)
                .setContentText(body)
                .setContentIntent(pendingIntent)
                .setAutoCancel(true)

            val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.notify(101, builder.build())
        }
    }

받은 remoteMessage를 가지고 title과 body 속성을 가져와서 notification안에 넣어서 푸쉬알림을 만들어줄 수 있다.

액티비티에서는 이 notification을 받을 채널을 만들어줘야 하므로 채널을 생성한다.

    @RequiresApi(Build.VERSION_CODES.O)
    // Notification 수신을 위한 체널 추가
    private fun createNotificationChannel(id: String, name: String) {
        val importance = NotificationManager.IMPORTANCE_DEFAULT
        val channel = NotificationChannel(id, name, importance)

        val notificationManager: NotificationManager
                = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

        notificationManager.createNotificationChannel(channel)
    }

📌 서버와 연동하여 FCM 수신

🔑 과정

  1. ClientApp을 Notification Server에 등록
  2. 앱을 켜면 각각의 앱을 구분하는 토큰을 Notification Server에서 발급
  3. 앱에서 Token을 Provider로 전송
  4. Provider에서 토큰 저장
  5. 앱에서 알림을 전송할 필요가 있을 때, 토큰 값과 함께 Notification Server에 요청
  6. 앱에 알림 수신

🔑 Firebase<->Spring Boot Push 알림 서버 구축

서버에서는 firebase로부터 비공개 키를 받아오고 안드로이드로 부터 앱의 토큰을 받아온다. 이 비공개 키로 파이어베이스가 서버에서 오는 데이터를 믿을 수 있다. 서버는 데이터와 앱의 토큰을 파이어베이스로 보내서 파이어베이스가 앱으로 전송해준다.

🔑 앱 상태와 메시지 종류에 따른 수신 처리

https://firebase.google.com/docs/cloud-messaging/android/receive?hl=ko&authuser=0

profile
컴퓨터와 교육 그사이 어딘가

0개의 댓글