# 결과물 미리보기
파이어 베이스를 통하여 내 안드로이드 기기에 알림을 보내는 기능을 구현해봤다. 강의영상을 참고하기도 했지만 달라진 것도 많기 때문에 Firebase와 안드로이드 공식문서를 많이 참고했다.
# 파이어베이스 연동하기 ( 안드로이드 스튜디오 범블비 버전 이상 )
시작하기에 앞서 파이어베이스를 내 안드로이드 프로젝트와 연동하는 작업이 필요하다. 안드로이드 스튜디오의 범블비 버전으로 올라감에 따라 build.gradle(project)에 추가하는 방법이 달려졌다. 이것때문에 살짝 애를 먹었다. 비슷한 것때문에 문제를 겪고 있는 사람들은 아래 내용을 참고하면 될 것 같다.
먼저 파이어 베이스에서 프로젝트를 만들어준다.
이후 앱을 추가해줄 것인데 여기서 프로젝트 ID와 json파일은 하라는대로 하면 된다.
## 범블비에서 Firebase SDK 추가
build.gradel(project)로 오면 아래 그림과 같이 가이드와 달라서 당황하게 될 것이다. 범블비 버전으로 업데이트 되면서 세부적인 내용은 settings.gradle에서 다룬다고 한다. 신경 쓸 필요 없이 build.gradle(project)에 아래처럼 코드를 추가해준다.
// build.gradle(proj)
buildscript {
dependencies {
classpath 'com.google.gms:google-services:4.3.10'
}
}
plugins {
id 'com.android.application' version '7.1.2' apply false
id 'com.android.library' version '7.1.2' apply false
id 'org.jetbrains.kotlin.android' version '1.6.10' apply false
}
task clean(type: Delete) {
delete rootProject.buildDir
}
그리고 Sync Now를 누르면 싱크가 완료된다.
이후 build.gradle(app)에서 진행하는 건 그대로 적어 사용하면 된다.
// build.gradle(app)
plugins {
// ...
}
apply plugin: 'com.google.gms.google-services'
dependencies {
// ...
// ...
implementation platform('com.google.firebase:firebase-bom:29.2.1')
implementation 'com.google.firebase:firebase-analytics-ktx'
implementation 'com.google.firebase:firebase-messaging-ktx'
}
이제 파이어 베이스와 연동은 끝냈다. 알림을 위한 코드를 작성하자
# 코틀린으로 코드 작성하기
순서는 다음과 같다.
- 안드로이드 디바이스에 부여된 토큰값 알아내기
- Firebase <-> 안드로이드 기기사이에서 알림을 주고 받을 채널 만들어주기
- NotificationCompat 빌더를 만들어 빌드하기
- notify를 통하여 빌더 호출하기
## 1. 안드로이드 디바이스에 부여된 토큰값 알아내기
물론 실제 서비스에서는 토큰값을 Firebase에 내부적으로 보내주거나 다른 방식을 사용하겠지만 이번 예제에서는 하드코딩을 통해서 토큰값을 알아냈다. Firebase SDK를 추가해줬기 때문에 Firebase관련된 것을 사용할 수 있다.
// MainActivity.kt
private fun initFirebase() {
FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->
if (task.isSuccessful) {
tokenTextView.text = task.result
}
}
}
물론 위 코드는 공식문서에 친절히 기재 돼 있다. 여기서 받은 토큰을 복사하여, 추후에 cloud message에서 send기능을 이용할때 토큰을 이용 하면 된다.
## 2.Firebase <-> 안드로이드 기기사이에서 알림을 주고 받을 채널 만들어주기
먼저 MyFirebaseMessagingService클래스를 새로 만들어준다, 그리고 FirebaseMessagingService()을 상속한다. 두 함수를 override해준다.
class MyFirebaseMessagingService : FirebaseMessagingService() {
override fun onNewToken(token: String) {
super.onNewToken(token)
}
override fun onMessageReceived(message: RemoteMessage) {
super.onMessageReceived(message)
}
}
또한 manifest에 아래 내용을 <application>안에 추가해준다
<service
android:name=".MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
이제 채널을 만들어줘야한다. 공식문서에 채널을 만드는 방법에 있는 코드를 가져와 사용하면 된다.
private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT)
channel.description = CHANNEL_DESCRIPTION
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
}
companion object {
private const val CHANNEL_NAME = "Emoji Party"
private const val CHANNEL_DESCRIPTION = "Emoji Party를 위한 채널"
private const val CHANNEL_ID = "채널 ID"
}
채널을 통해서 알림이 들어온다. 채널을 만들고 파이어베이스에서 알림을 보내면 채널이 생성됨을 볼 수 있다. 내 App 정보 -> 알림에 들어가 보면 알 수 있다.
## 3. NotificationCompat빌더를 만들어 빌드하기
override fun onMessageReceived(message: RemoteMessage) {
super.onMessageReceived(message)
createNotificationChannel() // 채널생성함수 호출
// 코드작성
}
위 함수를 override하여 메시지가 도착했을 경우의 행동을 정의 해줘야한다. message인자는 파이어 베이스에서 보낸 메시지다. 보내지는 메시지의 key와 vaule값을 통해 값을 받아온다.
val type = message.data["type"]?.let {
NotificationType.valueOf(it)
}
val textTitle = message.data["title"]
val body = message.data["body"]
type ?: return
textTitle은 제목, body는 내용을 담아줄 것이다. type은 이 알림이 어떤형태를 띄는 것인지 구분하기 위해 보내준다. 여기서는 일반형, bigtext, custom으로 3가지를 분류한다. 이 타입에 따라 도착하는 메시지의 형태가 다르다. 결과물 미리보기를 참고하면 된다.
만약 여러가지 타입을 대응하지 않는다면 저렇게 type별로 분기시킬 필요가 없지만, 3가지의 타입을 만들어야하기때문에 notify의 두번째 인자로 createNotification을 만들었다.
with(NotificationManagerCompat.from(this)) {
// notificationId is a unique int for each notification that you must define
notify(type.id, "빌더를 빌드하여 여기에 넣는다" ) // 두번째 인자로 빌더가 들어감
}
builder를 만드는것은 간단하다. 공식문서에 있는 코드를 가져오면 된다.
val builder = NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle(textTitle)
.setContentText(textContent)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
위처럼 builder을 만들어주고, 두번째 인자에서 builder.build()를 해주면 된다는 이야기이다. 그렇지만 type별로 분류하여 builder를 만들어지는 과정을 보자.
### 타입별로 builder분류하기
private fun createNotification(type: NotificationType?, textTitle:String?, body: String?) : Notification {
// 알림을 누르면 실행될 수 있게 intent를 만들어줌
val intent = Intent(this,MainActivity::class.java).apply {
putExtra("notificationType","${type?.title} 타입")
addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP) // 이미 해당 액티비티일때 인텐트가 연결되면 1개만 유지함
}
val resultPendingIntent = PendingIntent.getActivity(this,type!!.id,intent, FLAG_UPDATE_CURRENT)
// 기본 빌더
val builder = NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_notifications)
.setContentTitle(textTitle)
.setContentText(body)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(resultPendingIntent) // 알림을 누를경우 생기는 인탠트
.setAutoCancel(true)
Log.d("createNotification",type?.title.toString())
// 빌더에 type별로 속성을 추가해준다.
when(type){
NotificationType.NORMAL -> Unit
// 많은 text가 올 경우
NotificationType.EXPANDABLE -> {
builder.setStyle(NotificationCompat.BigTextStyle()
.bigText(bigEmoji))
}
//layout을 통해 custom하기
NotificationType.CUSTOM -> {
builder.setStyle(NotificationCompat.DecoratedCustomViewStyle())
.setCustomContentView(RemoteViews(packageName,R.layout.view_custom_notification)
.apply {
setTextViewText(R.id.title, textTitle)
setTextViewText(R.id.message, body)
})
}
}
// build()하여 반환함으로써 notify에서 한번에 사용
return builder.build()
}
위에서 소개한거와 같이 type별로 분류하는 것이다. 그리고 인탠트를 연결하여 해당알림 클릭시 액티비티가 열리게 하고, autocancel을 추가하여 클릭하며 알림이 없어지도록 했다.
## 4. notify를 통하여 빌더 호출하기
//notify호출하여 알림 실행
with(NotificationManagerCompat.from(this)) {
// notificationId is a unique int for each notification that you must define
notify(type.id, createNotification(type,textTitle,body))
}
재정의한 onMessageReceived 함수이다. 아까 본거와 같이 두번째 인자로 방금 만든 createNotification을 통해 빌더를 가져오게 한다.
# 마무리
사실 파이어베이스와 구글 공식문서 있는 코드를 가져와서 조금씩 바꿔주기만 했다. 확실히 코드를 가져와서 활용하는게 중요한거 같다. 내가 이런 코드를 하나하나 다 이해해서 쓰는건 말이 안되는것 같다.
안스에서도 디버깅 하는 방법을 알았다. 디버그 할 곳을 찍어두고 AVD를 실행시킨 후 안스에서 Run -> Attach Debugger to Android Process를 클릭하면 그곳에서 실행되면 멈춘다. 메시지가 잘 날라오는지 확인할때 유용했다.
여기에는 적지 않았지만 enum class를 사용해서 NORMAL, EXPANDABLE, CUSTOM의 값을 정의하고 title,id값을 다루니 무척 편리했다.
처음 SDK추가할때 꽤 애 먹었는데 이글이 유입이 잘 되서 많은 분들이 쉽게 해결했으면 좋겠다.
cloud message SEND 하는곳
파이어베이스 메시지 관련 문서
안드로이드 채널 관련 공식문서
안드로이드 알림 관련 공식문서
커스텀 알림 관련 공식문서