메세지를 보내기 위해서 토큰값을 알아야 하는데,
private fun initFirebase(){
FirebaseMessaging.getInstance().token
.addOnCompleteListener{ task->
if(task.isSuccessful){
binding.firebaseToken.text = task.result
Log.d("token", task.result.toString())
}
}
}
위 코드를 통해 얻을 수 있다. 쉽게 이야기하면 토큰을 가져오는 task가 성공할 경우,
토큰을 화면에 띄우고, 로그로 찍어준다.
FCM을 이용한 경우 FireBaseMessagingService 클래스를 상속받아 처리한다.
class FirebaseMessagingService: FirebaseMessagingService() {
override fun onNewToken(p0: String) {
//새 토큰 생성시 호출되는 함수
super.onNewToken(p0)
}
override fun onMessageReceived(remoteMessage: RemoteMessage) {
//메세지를 수신하였을때 호출되는 함수
super.onMessageReceived(remoteMessage)
}
}
onMessageReceived 함수에서 수신을 받고 custom action을 취할 수 있다.
<service android:name=".FirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
상속받은 클래스는 manifests에 service로 등록하여 백그라운드 환경에서도 호출되도록 한다.
FireBase -> Docs -> CloudMessaging -> send에 들어가면 테스트로 메세지를 보낼수 있다.
parent의 경우는 초기에 구성파일에서 확인할 수 있다.
private fun initChangeAlarmTimeButton(){
binding.changeAlarmTimeButton.setOnClickListener {
val calendar = Calendar.getInstance()
//TimPickerDialog 생성
TimePickerDialog(this, { picker, hour, minute ->
//설정한 시간 SharedPreference 에 저장
val model = saveAlarmModel(hour, minute, false)
renderView(model)
//기존 알람 삭제
cancelAlarm()
}, calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), false)
.show()
}
}
private fun saveAlarmModel(hour: Int, minute: Int, onOff: Boolean): AlarmDisplayModel{
val model = AlarmDisplayModel(
hour = hour,
minute = minute,
onOff = onOff
)
val sharedPreferences = getSharedPreferences(SHARED_PREFERENCE_KEY, Context.MODE_PRIVATE)
with(sharedPreferences.edit()){
putString(ALARM_KEY, model.makeDataForDB())
putBoolean(ON_OFF_KEY, model.onOff)
commit() //with 함수의경우 commit
}
return model
}
val newModel = saveAlarmModel(model.hour, model.minute, model.onOff.not())
renderView(newModel)
if (newModel.onOff){
//알람이 켜졌을때 알람을 등록
val calendar = Calendar.getInstance().apply {
set(Calendar.HOUR_OF_DAY, newModel.hour)
set(Calendar.MINUTE, newModel.minute)
if(before(Calendar.getInstance())){
add(Calendar.DATE, 1) //현재 시간보다 이전의 시간일 경우 하루뒤로 설정
}
}
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
val intent = Intent(this, AlarmReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(
this, ALARM_REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT)
alarmManager.setInexactRepeating(
AlarmManager.RTC_WAKEUP, //현재 시간을 기준으로 알람 설정
calendar.timeInMillis,
AlarmManager.INTERVAL_DAY,
pendingIntent
)
}else{
//꺼진 경우 알람 제거
cancelAlarm()
}
//온오프에 따라 처리
}
알람의 특성상 백그라운드에서 실행될 경우가 다수이기 때문에 PendingIntent를 이용하여 알람이 호출되면 broadCastReciever를 상속한 AlarmReceiver로 전달한다.
class AlarmReceiver: BroadcastReceiver(){
companion object{
const val NOTIFICATION_CHANNEL_ID = "1000"
const val NOTIFICATION_ID = 100
}
override fun onReceive(context: Context, intent: Intent) {
createNotificationChannel(context)
notifyNotification(context)
}
onReceive함수가 호출되면 알림을 생성한다.
<receiver android:name=".AlarmReceiver"
android:exported="false"/>
AlarmManager의 경우 Doze(잠자기 모드)에 영향을 받는다. 이에 영향을 받지 않기 위해서는
setAndAllowWhileIdle() 또는 setExactAndAllowWhileIdle()을 이용한다.
FCM 혹은 BroadCastReceiver를 호출받았다면 이를 사용자에게 알려줄 Notification을 만들어야 한다.
private fun createNotificationChannel(context: Context){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
val notificationChannel = NotificationChannel(
NOTIFICATION_CHANNEL_ID,
"기상 알림",
NotificationManager.IMPORTANCE_HIGH
)
NotificationManagerCompat.from(context).createNotificationChannel(notificationChannel)
}
}
private fun notifyNotification(context: Context){
with(NotificationManagerCompat.from(context)){
val builder = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
.setContentTitle("알림")
.setContentText("일어날 시간입니다.")
.setSmallIcon(R.drawable.background_ring)
.setPriority(NotificationCompat.PRIORITY_HIGH)
notify(NOTIFICATION_ID, builder.build())
}
}
notificationBuilder.setStyle(
NotificationCompat.DecoratedCustomViewStyle()
)
.setCustomContentView(RemoteViews(
packageName,
R.layout.new_custom_notification //따로 제작한 layout
).apply{
setTextViewText(R.id.title, title)
setTextViewText(R.id.text, text)
}
)
}
안유익한글 잘 봤습니다 :)