안녕하세요. 이번시간에는 FCM을 통해 메시지를 받는 방법에 대해서 포스팅을 작성하고자 합니다.
FCM이란?
Firebase 클라우드 메시징(FCM)은 무료로 메시지를 안정적으로 전송할 수 있는 교차 플랫폼 메시징 솔루션입니다. _(공홈)
특징으로는 각 플랫폼 환경별로 개발할 필요가 없이 Push 메시지를 전송할 수 있기 때문입니다.
또한 사용자는 낮은 배터리와 네트워크의 사용만으로도 메세지를 실시간으로 송수신 처리를 할 수 있다는 이점도 있습니다.
추가적인 FCM의 아키텍처를 확인하고 싶으시다면 아래 글을 확인해보세요.
https://firebase.google.com/docs/cloud-messaging/fcm-architecture?hl=ko
대략적으로 FCM이 무엇인지 그리고 사용하면 뭐가 좋은지에 대해서 알아보았습니다.
그러면 바로 FCM 구현을 해보도록 하겠습니다.
FCM 기능을 사용하기 앞서 해당 앱을 Firebase 프로젝트에 연동해야 하는 과정이 필요합니다. 해당 과정은 다른 블로그에서도 많이 자료가 나와있으니 이번 포스팅에서는 생략하도록 하겠습니다.
파이어 베이스 프로젝트에 해당 앱을 연동하고 구글 JSON 파일도 App 폴더에 추가해줬다면 APP Build 단에 아래 의존성을 추가해줍시다.
dependencies {
// Import the BoM for the Firebase platform
implementation platform('com.google.firebase:firebase-bom:28.4.1')
// Declare the dependencies for the Firebase Cloud Messaging and Analytics libraries
// When using the BoM, you don't specify versions in Firebase library dependencies
implementation 'com.google.firebase:firebase-messaging-ktx'
implementation 'com.google.firebase:firebase-analytics-ktx'
}
그 다음에는 특정 기기에 토큰을 받아 오기 위해서는 아래 코드를 이용해 줍니다.
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()
})
이제 메시지를 수신할 수 있도록 서비스를 등록해주도록 합니다.
해당 과정은 FirebaseMessagingService 클래스를 확장하는 service를 추가해주고, 메니페스트에 해당 서비스를 등록해주는 절차로 진행됩니다.
저는 FirebaseMessagingService를 상속하는 클래스의 이름을 MyFirebaseMessagingService 으로 했으나 이름은 자유롭게 변경이 가능합니다.
class MyFirebaseMessagingService : FirebaseMessagingService() {
//메세지를 수신할 때 호출된다.(메세지를 받을때) remoteMessage는 수신한 메세지이다.
override fun onMessageReceived(remoteMessage: RemoteMessage) {
if (remoteMessage.data.isNotEmpty()) {
Logger.d("Message data payload: ${remoteMessage.data}")
}
var notificationInfo: Map<String, String> = mapOf()
remoteMessage.notification?.let {
Logger.d("Message Notification Body: ${it.body}")
notificationInfo = mapOf(
"title" to it.title.toString(),
"body" to it.body.toString()
)
sendNotification(notificationInfo)
}
}
private fun scheduleJob() {
Logger.d("scheduleJob() 실행")
// [START dispatch_job]
val work = OneTimeWorkRequest.Builder(MyWorker::class.java).build()
WorkManager.getInstance(this).beginWith(work).enqueue()
// [END dispatch_job]
}
private fun handleNow() {
Logger.d("handleNow() 실행")
}
override fun onNewToken(token: String) {
Logger.w(TAG, "Refreshed token: $token")
sendRegistrationToServer(token)
}
private fun sendRegistrationToServer(token: String?) {
Log.d(TAG, "sendRegistrationTokenToServer($token)")
}
private fun sendNotification(messageBody: Map<String, String>) {
val intent = Intent(this, MainActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
val pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT)
val channelId = getString(R.string.default_notification_channel_id)
val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val notificationBuilder = NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle(messageBody["title"])
.setContentText(messageBody["body"])
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent)
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
//안드로이드 오레오 알림채널이 필요하기 때문에 넣음.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(channelId,
"Channel human readable title",
NotificationManager.IMPORTANCE_DEFAULT)
notificationManager.createNotificationChannel(channel)
}
notificationManager.notify(0, notificationBuilder.build())
}
}
해당 클래스를 메니페스트에도 추가를 해줍시다.
android:name=".MyFirebaseMessagingService" 에 들어가는 값은 MyFirebaseMessagingService클래스가 존재하는 경로를 적어주시면 됩니다. 만약에 MyFirebaseMessagingService가 service 패키지 안에 있다고 한다면 android:name에는 ".service.MyFirebaseMessagingService"가 됩니다.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.fcm">
<application
...
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- FCM service 추가 -->
<service
android:name=".MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
</manifest>
추가로 res/values/strings.xml 파일에 아래와 같이 FCM 기본 채널 id를 추가해줘야 합니다.
<resources>
<string name="default_notification_channel_id" translatable="false">fcm_default_channel</string>
</resources>
이제 알림 작성기를 통해 FCM 설정이 완료된 Android 클라이언트 앱에 메시지를 보내봅시다.
코드 중간에 나오는 Logger 라이브러리는 스틱코드를 참고하시면 가져다 쓸 수 있습니다.
https://stickode.tistory.com/275
https://stickode.com/detail.html?no=2559
참고
https://firebase.google.com/docs/cloud-messaging/android/receive?hl=ko
https://firebase.google.com/docs/cloud-messaging?hl=ko
https://firebase.google.com/docs/cloud-messaging/android/first-message?hl=ko
'안드로이드 코틀린' 카테고리의 다른 글
[Kotlin][Android] url로 가져온 이미지 다운로드하기 (0) | 2022.01.22 |
---|---|
[Kotlin][Android] Activity 이동 애니메이션 (0) | 2022.01.18 |
[Kotlin][Android] 이미지 url로 이미지 로딩하기 (0) | 2022.01.10 |
[Kotlin][Android] 비밀번호 hash 암호화하기 (0) | 2022.01.05 |
[Kotlin][Android] Bottom Sheet 프래그먼트 크기 확장하기. (1) | 2021.12.27 |