참고 사이트 : firebase cloud messaging 공식 홈페이지
firebase를 안드로이드 스튜디오에서 이용하기 위해 셋팅하기는
여기서 잘 설명이 되어있다.
혹은 firebase 홈페이지에서 프로젝트를 생성 후, 안드로이드 아이콘을 눌러서 앱 등록을 할 경우, 셋팅 과정이 잘 설명되어있음으로 그걸 따라가기로 하자.
백그라운드 외, 포그라운드 상태의 경우 콜백 함수로 메세지를 처리함. onMessageReceived() 이용 -> 포그라운드 상태에서는 메세지 따로 처리
전송방법 :
1. Firebase 콘솔을 사용, 알림 메세지를 전송할 수 있음.
+) 콘솔 이용에 필요한 토큰 가져오는 법 :
FirebaseMessaging.getInstance().token
.addOnCompleteListener{ task->
if(task.isSuccessful){
val token = task.result
Log.d("FIREBASE_TOKEN****************", token.toString())
}
}
{
"message":{
"token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"notification":{
"title":"Portugal vs. Denmark",
"body":"great match!"
}
}
}
클라이언트 앱에서 데이터 메세지를 처리.
백그라운드, 포그라운드 모두 콜백 함수로 메세지를 처리함. onMessageReceived() 이용 _ 메세지 수신 시 따로 처리를 해줘야함.
전송방법 :
(1) Cloud Functions 또는 앱 서버와 같은 신뢰할 수 있는 환경에서 Admin SDK 또는 FCM 서버 프로토콜을 사용하여 data 키만을 설정하여 전송
_ 알림 메세지 전송방법에도 있었지만 이 방법은, 실제로 메세지를 송신하려면 별도의 서버나 API 요청(CRUD)를 해야함. 글쓴이는 api 요청을 firebase 홈페이지에서 메세지 수신용으로 제공 중인 툴을 이용하여 함.
firebase 홈페이지 제공 _ api 이용하기
firebase api 링크에 들어가면 api를 이용할 수 있는 창이 뜨게 됨.여기서 parent의 string값에는 "projects/project_id"를 입력해주고, 푸시를 보낼 메세지 내용은 request body에 입력해주어 보내면 된다.
projects/project_id에서 "project_id"값은 안드로이드 스튜디오에 추가해준 google-services.json 파일에서 확인할 수 있다.
또한, "request body"에 넣어줄 메세지의 구조는 여기서 확인하도록 하자.
{
"message":{
"token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"data":{
"Nick" : "Mario",
"body" : "great match!",
"Room" : "PortugalVSDenmark"
}
}
}
(1) 서비스 추가하기.
<service
android:name=".MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
(2) meta-data 추가하기
<!-- 기본 알림 아이콘 및 색상을 설정 - 수신 알림 메시지에 별도 설정되지 않을 경우 사용됨. -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@drawable/ic_launcher_foreground" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="@color/teal_700" />
<!-- 기본 알림 채널 _ 객체 id 설정 - 수신 알림 메시지에 별도 설정되지 않을 경우 사용됨. -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="@string/noti_channel_id" />
override fun onNewToken(token: String) {
super.onNewToken(token)
Log.d(TAG, "Refreshed token: $token")
}
override fun onMessageReceived(remoteMessage: RemoteMessage){
super.onMessageReceived(remoteMessage)
//받은 remoteMessage의 값 출력해보기. 데이터메세지 / 알림메세지
Log.d("FirebaseMessagingService*************", "Message data : ${remoteMessage.data}")
Log.d("FirebaseMessagingService*************", "Message noti : ${remoteMessage.notification}")
//알림 메세지의 경우.
remoteMessage.notification?.let {
Log.d("FirebaseMessagingService*************", "Message Notification Body: ${it.body}")
//알림 메세지 _ 포그라운드에서도 알림 받은 것 처럼 받은 정보를 가지고 notification 구현하기.
sendNotification(remoteMessage.notification!!)
}
//데이터 메세지의 경우.
if(remoteMessage.data.isNotEmpty()) {
sendDataMessage(remoteMessage.data)
}
}
private fun createNotificationChannel(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
CHANNEL_ID,
CHANNEL_NAME,
NotificationManager.IMPORTANCE_DEFAULT
)
channel.enableLights(true)
channel.enableVibration(true)
(getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager).createNotificationChannel(channel)
}
}
companion object {
private const val CHANNEL_NAME = "FCM STUDY"
private const val CHANNEL_ID = "FCM__channel_id"
}
private fun sendDataMessage(data: MutableMap<String, String>) {
val intent = Intent(this, MainActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
val pendingIntent = PendingIntent.getActivity(
this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT
)
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
createNotificationChannel()
val notificationBuilder = NotificationCompat.Builder(this, CHANNEL_ID)
notificationBuilder.setContentTitle(data["title"])
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentText(data["message"])
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(pendingIntent)
.setAutoCancel(true)
//큰 이미지가 따로 올 경우. data에 imageUrl이 들어있을 경우
if(data["image"] != null) {
Log.d("imageUri2***********************", data["image"].toString())
Glide.with(applicationContext)
.asBitmap()
.load(data["image"])
.into(object : CustomTarget<Bitmap>() {
override fun onResourceReady(
resource: Bitmap,
transition: Transition<in Bitmap>?
) {
Log.d("imageObject2*********************", resource.toString())
notificationBuilder.setStyle(NotificationCompat.BigPictureStyle()
.bigPicture(resource))
}
override fun onLoadCleared(placeholder: Drawable?) {}
})
}
notificationManager.notify(100, notificationBuilder.build() )
}
title, content, image를 함께 넣은 경우 :
// 추가로 해 볼 것들 :