FCM 푸시 알림을 사용하는 방법
1. 파이어베이스 프로젝트 추가
2. 프로젝트 설정 -> 앱 등록 (Android 선택)
3. 앱 등록 절차 (앱 등록, 구성 파일 다운로드)
패키지 이름은 AndroidManifest.xml에서 확인 가능하고, SHA-1 인증서는 signingReport을 더블클릭하면 AndroidStudio 콘솔에서 확인할 수 있습니다.
4. 앱 등록 절차 (파이어베이스 SDK 추가)
해당 절차는 파이어베이스 절차에 따라 그대로 진행해주시면 됩니다.
AndroidManifest.xml에서 아래와 같이 Permission과 Service를 추가한 후 아래의 코드를 사용한 후 이 부분이 중요합니다. "클라우드 메시징" 라이브러리도 추가해주시면 됩니다. 관련 정보는 아래에서 확인할 수 있습니다.
firebase.google.com/docs/android/setup?hl=ko%EF%BB%BF
FirebaseMessagingService는 백그라운드에서 앱의 알람을 수신하는 것 외에 다른 방식으로 메시지를 처리하려는 경우에 필요합니다. 포그라운드 앱의 알림, 수신, 데이터 페이로드 수신, 업스트림 메시지 전송 등을 수행하려면 이 서비스를 확장해주시면 됩니다.
<uses-permission android:name="android.permission.INTERNET" />
<application
...>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".MyFirebaseMessagingService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
package com.example.fcmex
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.ContentValues.TAG
import android.content.Context
import android.content.Intent
import android.media.RingtoneManager
import android.os.Build
import android.os.Build.VERSION_CODES.O
import android.util.Log
import androidx.core.app.NotificationCompat
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
class MyFirebaseMessagingService : FirebaseMessagingService() {
// 토큰이 새로 만들어질때나 refresh 되는 경우
override fun onNewToken(token: String) {
Log.d(TAG, "new Token: $token")
// 토큰 값을 따로 저장해둔다.
//val pref = this.getSharedPreferences("token", Context.MODE_PRIVATE)
//val editor = pref.edit()
//editor.putString("token", token).apply()
//editor.commit()
sendRegistrationToServer(token)
Log.d(TAG, "성공적으로 토큰을 저장함")
super.onNewToken(token)
}
private fun sendRegistrationToServer(token: String) {
}
// 메시지를 받을 경우
override fun onMessageReceived(remoteMessage: RemoteMessage) {
Log.d(TAG, "From: " + remoteMessage.from)
// Notification 메시지를 수신할 경우는
// remoteMessage.notification?.body!! 여기에 내용이 저장되어있다.
if (remoteMessage.notification != null && remoteMessage.data.isNotEmpty()){
Log.d(TAG, "공지 도착 : 데이터 있습니다.")
Log.d(TAG, "Notification Message Title: " + remoteMessage.notification?.title)
Log.d(TAG, "Notification Message Body: " + remoteMessage.notification?.body)
Log.d(TAG, "바디 : ${remoteMessage.data["body"].toString()}")
Log.d(TAG, "타이틀 : ${remoteMessage.data["title"].toString()}")
sendNotification(remoteMessage)
}else if(remoteMessage.notification != null && !remoteMessage.data.isNotEmpty()){
Log.d(TAG, "공지 도착 : 데이터 없습니다.")
Log.d(TAG, "Notification Message Title: " + remoteMessage.notification?.title)
Log.d(TAG, "Notification Message Body: " + remoteMessage.notification?.body)
sendNotification(remoteMessage)
}
else {
Log.d(TAG, "수신에러 : Notification가 비어있습니다. 메시지를 수신하지 못했습니다.")
Log.d(TAG, "Notification값 : ${remoteMessage.notification.toString()}")
Log.d(TAG, "수신에러 : data가 비어있습니다. 메시지를 수신하지 못했습니다.")
Log.d(TAG, "data값 : ${remoteMessage.data.toString()}")
}
}
private fun sendNotification(remoteMessage: RemoteMessage) {
// RequestCode, Id를 고유값으로 지정하여 알림이 개별 표시되도록 함
val uniId: Int = (System.currentTimeMillis() / 7).toInt()
// 일회용 PendingIntent
// PendingIntent : Intent 의 실행 권한을 외부의 어플리케이션에게 위임한다.
val intent = Intent(this, MainActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) // Activity Stack 을 경로만 남긴다. A-B-C-D-B => A-B
//intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
val pendingIntent = PendingIntent.getActivity(this, uniId, intent, PendingIntent.FLAG_ONE_SHOT)
// 알림 채널 이름
val channelId = resources.getString(R.string.firebase_notification_channel_id)
// 알림 소리
val soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val notificationBuilder = NotificationCompat.Builder(this, channelId)
//data가 있을땐 제목, 메시지를 data 값으로 변경
if (remoteMessage.data.isNotEmpty()){
// 알림에 대한 UI 정보와 작업을 지정한다.
notificationBuilder.setSmallIcon(R.mipmap.ic_launcher) // 아이콘 설정
.setContentTitle(remoteMessage.data["title"].toString()) // 제목
.setContentText("실행 중 : "+ remoteMessage.data["body"].toString()) // 메시지 내용
.setAutoCancel(true)
.setSound(soundUri) // 알림 소리
.setContentIntent(pendingIntent) // 알림 실행 시 Intent
}else{
// 알림에 대한 UI 정보와 작업을 지정한다.
notificationBuilder.setSmallIcon(R.mipmap.ic_launcher) // 아이콘 설정
.setContentTitle(remoteMessage.notification!!.title.toString()) // 제목
.setContentText("실행 중 : "+ remoteMessage.notification!!.body.toString()) // 메시지 내용
.setAutoCancel(true)
.setSound(soundUri) // 알림 소리
.setContentIntent(pendingIntent) // 알림 실행 시 Intent
}
val notificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// 오레오 버전 이후에는 채널이 필요하다.
if (Build.VERSION.CODENAME >= O.toString()) {
val channel = NotificationChannel(channelId, "Notice", NotificationManager.IMPORTANCE_DEFAULT)
notificationManager.createNotificationChannel(channel)
}
// 알림 생성
Log.d(TAG, "푸시 알람을 생성합니다.")
notificationManager.notify(uniId, notificationBuilder.build())
}
}
5. Cloud Messaging 생성
이제 푸시 알림을 테스트하기 위해 메시지를 생성해보겠습니다.
(1. 알림
- 알림 제목 : FcmEx
- 알림 텍스트 : 메시지 도착 확인
(2. 타겟
- 사용자 타겟팅 조건 : 앱 -> 패키지 선택
(3. 예약
- 대상 사용자에게 전송 : 지금
6. 푸시 알림 확인
- 백그라운드의 경우 포그라운드의 경우
7. 예외
만약 메시지가 도착하지 않는 경우 google-services.json
파일의 코드를 확인해주세요.
"api_key": [
{
"current_key": "AIzaSyDpsd...cSdtXeDILfk"
}
]
구글 클라우드 플랫폼에서 API 키 값의 제한 세항을 설정한 경우 Firebase Installations API
를 추가해주지 않으면 메시지가 도착하지 않습니다.
'Android' 카테고리의 다른 글
[Android] Activity 생명주기 (0) | 2021.04.09 |
---|---|
AndroidProgramming - Listener 등록 (Kotlin) (0) | 2021.04.08 |
Kakao Map API (카카오 지도 API) (0) | 2021.03.29 |
Extension functions(확장 함수) (0) | 2021.03.28 |
StateBar (상태바) : 색상 변경 (0) | 2021.03.28 |