기본적으로 알림을 보내는 방법이나 간단한 예시는 공식문서가 더 잘 나와있으니 그곳을 참고하시고 나서 이 문서를 보시면 좋을 것 같습니다.
안드로이드 알림만들기 공식문서
안드로이드 알람 예약 공식문서
또 기본적인 개념잡기에는 아래의 코드랩이 큰 도움이 됩니다.
안드로이드 Notification 코드랩 실습
알림을 정기적으로 보내고싶은데 (매일 오전 8시30분) 구글의 AlarmManager에 있는 setRepeating등등의 반복 알람은 이제 배터리 이슈때문인지 정확한 시간대에 알림을 보내주지 않습니다. 사용자가 대기모드에서 핸드폰을 꺠울 때 모아서 보내주는 듯 합니다.
하지만 매일 정기적으로 보내고 싶다면 일회성 알람을 계속 등록시키는 방식을 써야 합니다. (간단히 될 코드가 먼 산을 돌아가게 되네요..구글 네이놈..)
우선 제가 한 방식도 아주 주먹구구 방식이지만 그래도 오래동안 고민한 결과를 공유하고 싶어서 글을 씁니다.
대충의 흐름은 이렇습니다.
- NotificationChannel을 만들어줍니다.
(앱의 시작지점즈음에 만들어 주는게 좋습니다.)- AlarmManager로 일회성 알람을 예약해줍니다.
- AlarmManager가 해당 시간이 되면 OnReceive()함수를 실행하게됩니다.
OnReceive()함수에서 노출시키고 싶은 Notification을 만들어 보내고 다음 알람을 예약해줍니다.
이렇게 예약한 알람은 다음 예약한 시간에 다시 OnReceive()함수를 실행하게되고
다시 Notification을 띄우고, 다음 알람을 예약하게 됩니다.
톱니바퀴처럼 하루하루 돌아가는거죠.
이렇게 채널 만드는건 다른 곳이나 공식문서에 더 좋은 예시들이 많습니다. 참고만 하세요.
채널 설정은 한번만 해두면 계속 그 설정을 쓰기 때문에 알람이 울릴때마다 만들 필요는 없습니다.
여러 다른 참고자료에서 알람이 울릴때마다 새로 채널을 만들어 주는 경우를 봤는데 그럴 필요는 없어 보입니다. (구글 코드랩에서 채널을 한번만 만들더라구요)
앱 시작지점 즈음에 한번만 만들게 위치해주시면 좋을 것 같습니다.
private fun createChannel(channelId: String, channelName: String) {
// TODO: Step 1.6 START create a channel
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationChannel = NotificationChannel(
channelId,
channelName,
// TODO: Step 2.4 change importance
NotificationManager.IMPORTANCE_HIGH
)// TODO: Step 2.6 disable badges for this channel
.apply {
setShowBadge(false)
}
notificationChannel.enableLights(true)
notificationChannel.lightColor = Color.RED
notificationChannel.enableVibration(true)
notificationChannel.description = "Notification Channel 입니다. "
val notificationManager = getSystemService(
NotificationManager::class.java
)
notificationManager.createNotificationChannel(notificationChannel)
}
// TODO: Step 1.6 END create a channel
}
시스템 서비스인 AlarmManager를 불러오고 원하는 시간대를 설정하고 PendingIntent에 넣을 Intent를 만들고 PendingIntent를 만듭니다. (Intent에는 자신이 보내고 싶은 데이터들을 담아서 보낼수 있습니다. receive할때 받아서 써야하는 경우에 잘 쓰면 될것 같습니다.)
그리고
val alarmManager = getSystemService(ALARM_SERVICE) as AlarmManager
val intent = Intent(this, MyReceiver::class.java)
intent.putExtra("hour", hour)
intent.putExtra("minute", minute)
val calendar: Calendar = Calendar.getInstance().apply {
timeInMillis = System.currentTimeMillis()
set(Calendar.HOUR_OF_DAY, hour)
set(Calendar.MINUTE, minute)
}
val pendingIntent = PendingIntent.getBroadcast(
this, id, intent,
//PendingIntent.FLAG_NO_CREATE
PendingIntent.FLAG_UPDATE_CURRENT or
PendingIntent.FLAG_IMMUTABLE
)
alarmManager.setExactAndAllowWhileIdle(
AlarmManager.RTC_WAKEUP,
calendar.timeInMillis,
pendingIntent
)
BroadcastReceiver()를 하나 잡아주고 onReceive()함수에서 알림을 보내고 다음 알람을 예약하면 됩니다.
class MyReceiver : BroadcastReceiver() {
lateinit var notificationManager: NotificationManager
override fun onReceive(context: Context, intent: Intent) {
notificationManager = context.getSystemService(
Context.NOTIFICATION_SERVICE) as NotificationManager
val id = intent.getIntExtra("id",0)
val text = intent.getStringExtra("text")
val hour = intent.getIntExtra("hour", -1)
val minute = intent.getIntExtra("minute", -1)
val temp = intent.getSerializableExtra("calendar")
//알림을 만들어 보냅니다
notificationManager.sendNotification(id, context)
val alarmManager = context.getSystemService(AppCompatActivity.ALARM_SERVICE) as AlarmManager
val calendar: Calendar = Calendar.getInstance().apply {
timeInMillis = System.currentTimeMillis()
set(Calendar.HOUR_OF_DAY, hour)
set(Calendar.MINUTE, minute)
}
calendar.add(Calendar.DAY_OF_MONTH, 1)
val pendingIntent = PendingIntent.getBroadcast(
context, id, intent,
//PendingIntent.FLAG_NO_CREATE
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
//알람매니저에 다음 알람을 예약시킵니다.
alarmManager.setExactAndAllowWhileIdle(
AlarmManager.RTC_WAKEUP,
calendar.timeInMillis,
pendingIntent
)
}
}
Notification을 만들고 알리는 notificationManager.sendNotification() 메소드는 아래 와 같이 만들었으니 참고하세요.
NotificationManager에 커스텀 함수를 등록시키는 느낌입니다.
fun NotificationManager.sendNotification(notification_id: Int, applicationContext: Context)
{
val stringArray : Array<String> = arrayOf(
"a", "b", "c", "d", "e", "f", "g", "h","i", "j", "k", "l", "m", "n", "o"
)
val random = Random()
val num = random.nextInt(15)
// 여기 빌더가 여러분이 보고싶어하는 파트일 듯합니다.
val builder = NotificationCompat.Builder(
applicationContext,
"Notification_Channel_id"
)
.setSmallIcon(android.R.drawable.star_big_on) // 아이콘
.setContentTitle(notification_id.toString() + "Make a Smile") // 제목
.setContentText(stringArray[num]) // 내용
//.setContentIntent(contentPendingIntent)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true)
//NotificationManager의 notify함수를 불러 알림을 보냅니다.
notify(notification_id, builder.build())
}
안녕하세요.
안드로이드 초보개발자입니다...
제가 지금 알람 매니저로 하루에 한번 알림을 보내는데
알림은 오는데 잠금 화면에서 wake up이 안돼서
powermanager부분도 확인해봤지만 화면 깨워주는 부분은 다 depricate됐더라구요.
혹시 알람작업하시다가 이런 이슈는 없으셨나요?