취업을 하고 나서 여러 가지를 배우며 블로그에 정리를 하고 있다.
깊게 배우지 못하고, 얕게 배우지만,
이 마저도 정리하기 위해 글을 쓴다.
부족한 설명은 이해해주길 바란다.
FCM이란
앱을 사용하는 이용자에게
포그라운드나 백그라운드 상태에서
(포그라운드 : 앱이 실행중인 상태)
(백그라운드 : 앱이 꺼진상태)
원하는 메시지를 전달하기 위한 방법이다.
예전에는 GCM이라고 구글에서 제공하는 클라우드 메세징이 있었다는데,
이 FCM으로 대체되었다고 한다.
FCM에는 두 가지 형태가 있는 데
하나는 Notification이고, 하나는 data이다.
두가지 차이점은 아래와 같다.
* 전자는 앱이 실행 중(포그라운드) 일 때만 푸시 알림이 오고,
* 후자는 실행 중이거나 백그라운드(앱이 실행 중이지 않을 때) 알림이 온다.
* 보통은 Data를 쓰지 않을 이유가 없기 때문에 특별한 상황이 아닌 이상 Data를 사용하자.
그렇다.. 곧 Data를 쓰는 것이 낫겠다.
그럼 어디 한번 FCM을 간단히 사용해보자.
파이어 베이스 사이트에서 프로젝트를 만든 뒤에
안드로이드 스튜디오에 돌아와서
우선 상단 탭에 Tools ->에서 파이어 베이스를 클릭한다.
클라우드 메세징을 클릭하고,
Set up Cloud Messaging을 클릭하고, 나와있는 순서대로
진행하면 된다.
진행 후에 코드를 기록하겠다.
우선
build.gradle이다.
파이어 베이스에서 기본 설정으로 넣은 것들도 포함되어 있다.
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = "1.4.32"
repositories {
google()
jcenter()
}
dependencies {
classpath "com.android.tools.build:gradle:4.1.3"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.gms:google-services:4.3.5'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
build.gradle(app)이다.
apply plugin: 'com.google.gms.google-services'
dependencies {
implementation platform('com.google.firebase:firebase-bom:26.8.0')
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'com.google.firebase:firebase-messaging-ktx'
implementation 'com.google.firebase:firebase-analytics-ktx'
}
위에 라이브러리는 아마 파이어베이스 연동 시에 전부 적어놓았을 것이다.
혹시 몰라서 적어둔다.
매니페스트도 아래와 같이 작성해준다.
<uses-permission android:name="android.permission.INTERNET"/>
<service
android:name=".MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
아까 안내에 따라 적었을 것이다.
그러면 MyFirebaseMessagingService 코틀린 파일을 만들어 보자.
class MyFirebaseMessagingService : FirebaseMessagingService() {
/** 장단점
* 메세지를 보내면 20초 정도 후에 알람이 도착한다
* */
/** FireBase Cloud Messaging(FCM)*/
/** 알아야 할 사실
* 푸시 알림으로 보낼 수 있는 메세지는 2가지 유형이 있는데,
*
* 하나는 Notification이고, 하나는 Data이다.
* 전자는 앱이 실행중(포그라운드)일 때만 푸시 알림이 오고,
* 후자는 실행중이거나 백그라운드(앱이 실행중이지 않을때) 알림이 온다.
* 보통은 Data를 쓰지 않을 이유가 없기 때문에 특별한 상황이 아닌 이상 Data를 사용하자.
* */
//메세지를 수신할 때 호출된다.(메세지를 받을때) remoteMessage는 수신한 메세지이다.
override fun onMessageReceived(remoteMessage: RemoteMessage) {
Log.d(TAG, "From: ${remoteMessage.from}")
//메시지에 데이터 페이로드가 포함되어 있는지 확인한다. 여기서 페이로드란 전송된 데이터를 의한다.
//데이터 값이 있는지 없는 지 확인 할때 쓰인다.
if (remoteMessage.data.isNotEmpty()) {
Log.d(TAG, "Message data payload: ${remoteMessage.data}")
if (true) {
//데이터를 처리하는데 10초 이상이 걸리면 workManager를 사용한다.
scheduleJob()
} else {
//10초이내에 시작하면 아래 메서드를 실행한다.
handleNow()
}
}
//메세지에 알림 페이로드가 포함되어 있는지 확인한다.
remoteMessage.notification?.let {
Log.d(TAG, "Message Notification Body: ${it.body}")
}
}
//FirebaseInstanceIdService는 이제 사라짐. 이제 이걸 사용한다.
//FCM 등록 토큰이 업데이트되면 호출된다.
//토큰이 처음 생성될때 여기에서 토큰을 검색할 수 있다.
override fun onNewToken(token: String) {
Log.d(TAG, "Refreshed token: $token")
//이 앱 인스턴스에 메시지를 보내려는 경우나 서버 측에서 이 앱 구독을 관리한다면,
//FCM 등록 토큰을 앱 서버에 추가합니다.
sendRegistrationToServer(token)
}
//메세지 페이로드가 있을 때 실행되는 메서드(10초 이상 걸릴 떄 호출 된다)
//WorkManager를 사용하여 비동기 작업을 예약한다.
private fun scheduleJob() {
// [START dispatch_job]
val work = OneTimeWorkRequest.Builder(MyWorker::class.java).build()
WorkManager.getInstance(this).beginWith(work).enqueue()
// [END dispatch_job]
}
//메세지 페이로드가 있을 때 실행되는 메서드(10초 이내로 걸릴 때 호출된다)
//BroadcastReceivers에 할당 된 시간을 처리합니다.
private fun handleNow() {
Log.d(TAG, "Short lived task is done.")
}
//타사 서비에 토큰을 유지해주는 메서드입니다.
//사용자의 FCM등록 토큰을 서버 측 계정에 연결하려면 이 방법을 사용합니다.
//응용 프로그램에서 유지 관리를 합니다.
//파라미터에 들어있는 토큰은 새로운 토큰입니다.
private fun sendRegistrationToServer(token: String?) {
//이 메서드를 구현하여 앱 서버에 토큰을 보냅니다.
Log.d(TAG, "sendRegistrationTokenToServer($token)")
}
//수신 된 FCM 메시지를 포함하는 간단한 알림을 만들고 표시합니다.
//파라미터에 있는 messageBody에는 FCM 메세지 본문이 담겨져 있습니다.
private fun sendNotification(messageBody: 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.sooyeol)
.setContentTitle(getString(R.string.fcm_message))
.setContentText(messageBody)
.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())
}
companion object {
private const val TAG = "MyFirebaseMsgService"
}
}
코드와 설명은 공식문서를 통해 정리해서 적어 두었다.
각 메서드 별로 메시지를 수신했을 때 어떤 식으로 메서드가 실행되는지 정리를 해보았다.
위 코드에서 말하는 페이로드는 전달받은 데이터를 말한다.
그리고 페이로드를 받아올 때, 10초 이상에 시간이 걸리면
장기 실행 작업에 추가하기 위한 클래스를 만들어야 한다.
아래와 같이 만들어 주면 될 것이다.
class MyWorker(appContext: Context, workerParams: WorkerParameters) : Worker(appContext, workerParams) {
override fun doWork(): ListenableWorker.Result {
Log.d(TAG, "Performing long running task in scheduled job")
//여기에 장기실행작업을 추가합니다.
return ListenableWorker.Result.success()
}
companion object {
private val TAG = "MyWorker"
}
}
그러고 나서 메인 액티비티에 등록된 토큰을 가져오는 메서드를 넣어주면 끝이 난다.
class MainActivity : AppCompatActivity() {
val TAG : String = "안녕"
@SuppressLint("StringFormatInvalid")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//메인 액티비티에서 등록 토큰 가져오기
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()
})
}
}
이렇게 하고 나서 다시 파이어 베이스로 돌아가 보자.
왼쪽 탭에 클라우드 메세징 탭을 누르고 , 앱에 보낼 메시지를 적어주고,
시간을 입력하면 위와 같이 완료가 되었다고 뜰 것이다.
그러면 기기에 따라서 시간은 다르지만, (나 같은 경우는 20초 후에 메시지가 왔다.)
아래와 같이 메시지가 온 것을 확인할 수 있을 것이다.
이런 식으로 메시지가 온 것을 확인할 수 있다.
FCM 끝.
Android Kotlin/ 단말기를 흔들었을때 호출되는 메서드 TIL # 32 (0) | 2021.05.17 |
---|---|
안드로이드 스튜디오 GitHub 오류 / 422 unprocessable entity - repository creation failed. [repository; description]custom: description control characters are not allowed TIL # 31 (0) | 2021.05.16 |
안드로이드 코틀린 / lottie Animation을 이용해 인스타그램 하트기능 만들기/ TIL # 30 (2) | 2021.05.15 |
안드로이드 코틀린 리사이클러뷰 사용법 #TIL 29 (0) | 2021.04.27 |
안드로이드 코틀린 Intent 알아보기 TIL #28 (2) | 2021.04.26 |
안드로이드 코틀린 Button 리스너와 setText 사용하기 TIL # 27 (0) | 2021.04.22 |
안드로이드 코틀린 뷰 바인딩 View Binding TIL #26 (0) | 2021.04.22 |
#TIL 24 안드로이드 코틀린 뷰페이저2 구현하기 (0) | 2021.04.20 |