
앱이 Foreground 상태가 아니어도 사용자에게 앱의 정보를 적시에 제공하고 알림을 주는 데 사용되는 앱 UI 외부에 표시되는 메시지다.
사용자는 메시지를 받기만 하는 것이 아닌, 탭 하여 앱을 열거나 특정 작업을 바로 수행할 수 있다.
Foreground Service 사용 시 Notification을 구현해 줘야 한다.
Notification UI는 여러 요소로 구성되어 있다. 설정에 따라 특정 요소를 표시하지 않을 수 있고, Custom 할 수도 있다.
🔹작은 아이콘 (필수)
🔹앱 이름 (시스템 제공)
🔹타임 스탬프 (시스템 제공)
🔹큰 아이콘 (선택)
🔹제목 (선택)
🔹내용 (선택)
Custom 레이아웃을 만들 수 있지만, 기기 호환성을 고려하여 시스템 템플릿을 사용하는 것이 권장된다.
시스템이 제공하지 않는 필수 요소인 '작은 아이콘'은 직접 설정해 줘야 한다.
Android 13 이상 : Notification 권한을 허용받아야 한다.
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
Android 8 이상 : Notification Channel을 사용해야 한다.
Android 8 이상부터는 Notification을 Channel 별로 할당해야 한다. 이로인해 앱 Notifiacion들에 Channel이라는 분류가 생기고, Channel마다 시각 및 오디오 제어, 중지, 중요도 설정, 방해금지 모드 설정 등을 할 수 있다.
Android 7 이하 : Notification이 앱 별로 관리된다.
앱마다 하나의 Channel이 생성된다. 따라서 Notification 생성 시 따로 Channel을 할당해 줄 필요가 없다.
🔹 Notification 권한을 얻는다. Androd 13 이상
🔹 Notification Channel 객체를 만들고 설정한다. Android 8 이상
🔹 Notification Manager로 Channel을 등록한다. Android 8 이상
🔹 Notification Builder 객체를 만들고 설정한다.
🔹 Notification Builder로 Notification을 만들고 Notify 한다.
1. Notification 권한을 얻는다. Androd 13 이상
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
- 사용자에게서 Notification 권한을 획득하기 위한 작업이 필요하다.
2. Notification Channel 객체를 만들고 Notification Manager로 Channel을 등록한다. Android 8 이상
private fun createNotificationChannel() {
// Channel은 Android 8 이상에서만 사용
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(CHANNEL_ID, CHANNEL_NAME, IMPORTANCE).apply {
// Channel 설정 (소리, 색, 진동 등)
description = "Description Text"
setShowBadge(true)
setSound(uri, audio)
}
val notificationManager: NotificationManager =
getSystemService(NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
}
- Android 8 이상에서만 Channel 생성 및 설정
- CHANNEL_ID, CHANNEL_NAME : 원하는 Channel Id, Name 입력
- IMPORTANCE : NotificationManager의 Importance
NotificationManager.IMPORTANCE_HIGH: 긴급 상황 & 알림음이 울리며 헤드업으로 표시
NotificationManager.IMPORTANCE_DEFAULT: 높은 중요도 & 알림음이 울림
NotificationManager.IMPORTANCE_LOW: 중간 중요도 & 알림음이 울리지 않음
NotificationManager.IMPORTANCE_MIN: 낮은 중요도 & 알림음이 없고 상태표시줄에도 뜨지 않음
- NOTIFICATION_SERVICE : Context.class 상수
getSystemService(NotificationManager::class.java) 가능
- Notification Manager 대신, NotificationManagerCompat 사용시
NotificationManagerCompat.from(context).createNotificationChannel(channel)
3. Notification Builder 객체를 만들고 설정한다.
// API Level 26 (Android 8) 이상
// Notification.Builder(context: Context!, channelld: String!)
// API Level 26 (Android 8) 미만
// Notification.Builder(context: Context!)
private fun buildNotification(context: Context) : NotificationCompat.Builder {
val builder : NotificationCompat.Builder
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// 26이상에서 Channel 필요
builder = NotificationCompat.Builder(context, CHANNEL_ID)
} else {
// 26미만에서 Priority 설정 필요
builder = NotificationCompat.Builder(context)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
}
// builder 세팅
builder.setSmallIcon(android.R.drawable.ic_noification_small)
builder.setContentTitle("Title")
builder.setContentText("Message")
builder.setAutoCancel(true)
return builder
}
- Android 버전에 따른 Builder 분기 처리 필요
Android 8 이상에서는 Channel을 넣어줘야 하며 Channel에 Priority가 설정되어 있지만,
Android 8 미만에서는 Builder에 직접 설정해 줘야 한다. (필수)
- builder smallIcon은 설정을 해줘야 한다. (필수)
Time, Style, 클릭 시 Action 등도 설정할 수 있다.
4. Notification Builder로 Notification을 만들고 Notify 한다.
with(NotificationManagerCompat.from(context)) {
notify(NOTIFICATION_ID, builder.build())
}
- Notification Update 시 원하는 Notification ID를 넣어 주면 된다.
Notification ID(int)와 Channel ID(String)는 다르다.
- 두 번째 인자로 builder.build(), 즉 Notification 객체가 들어간다.
ex. Test Code in Activity
companion object {
const val CHANNEL_ID = "CHANNEL_ID"
const val CHANNEL_NAME = "CHANNEL_NAME"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_notification)
val btn : Button = findViewById(R.id.btn_send_notify)
btn.setOnClickListener {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
// 권한 허가 안하면 실행 불가
checkPermission()
}
//NotificationChannel 생성 및 등록
createNotificationChannel()
//NotificationBuilder 설정
val builder: NotificationCompat.Builder = buildNotification()
//Notification 실행
with(NotificationManagerCompat.from(this)) {
notify(1, builder.build())
}
}
}
private fun checkPermission() {
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.POST_NOTIFICATIONS
) != PackageManager.PERMISSION_GRANTED
) {
Toast.makeText(this, "앱 설정 -> Notification 권한 허용 필요", Toast.LENGTH_SHORT).show()
}
}
private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val importance = NotificationManager.IMPORTANCE_DEFAULT
val channel = NotificationChannel(CHANNEL_ID, CHANNEL_NAME, importance).apply {
description = "Extra builder setting"
}
val notificationManager: NotificationManager =
getSystemService(NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
}
private fun buildNotification() : NotificationCompat.Builder {
val builder : NotificationCompat.Builder
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
builder = NotificationCompat.Builder(this, CHANNEL_ID)
} else {
builder = NotificationCompat.Builder(this)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
}
builder.setSmallIcon(android.R.drawable.ic_notification_overlay)
.setContentTitle("Title")
.setContentText("Content!!")
return builder
}
- Test 용으로 간단하게 구현된 코드로, 여러 요소를 더 고려해야 한다.
ChannelId, ChannelName, NotificationId 등은 여러 곳에서 쓰일 수 있다면 const를 고려해 보자.
권한이 있을 때, Notification을 실행해야 한다.
Activity가 아닌 곳에서 사용할 때는 context, notification manager, pending intent 등을 구현할 때 다른 부분이 생긴다.
Channel, Builder 설정이 필요하면 해준다.
Channel Name : 앱 설정의 Channel 명에 나타나는 값
Channel ID : 앱 설정의 Channel이 분류되는 값
Notification ID : 상단에 표시되는 Notification이 분류되는 값
즉, Channel ID를 다르게 하면 앱 설정에 여러 Channel이 생성 되고, Notification ID를 다르게 하면 앱 상단에 알림이 여러 개 뜬다.
플라밍고로 AndroidStudio를 업데이트하며 notify 쪽에 오류 라인이 생겼다. 그럼에도 실행은 된다.
권한 체크하는 부분을 만들어 주면 사라지는데,
compat이 아닌 notification manager를 쓰면 생기지 않는다.
권한 Library를 사용하면 그대로 오류 라인이 생겼다.
권한 체크하는 코드가 다른 곳에 있을 경우 권한 체크가 되어도 생긴다.
Notification 체크가 아닌, 다른 권한만 체크해도 생기지 않는다.
with(NotificationManagerCompat.from(this)) {
notify(1, builder.build())
}
https://developer.android.com/guide/topics/ui/notifiers/notifications?hl=ko
https://developer.android.com/training/notify-user/build-notification?hl=ko#kotlin
https://developer.android.com/training/notify-user/expanded?hl=ko
https://www.droidcon.com/2022/11/28/all-about-notifications-in-android/
수정 및 개선할 내용을 알려주시면 반영하겠습니다.
읽어주셔서 감사합니다, 좋은 하루 보내세요!
좋은 글 감사합니다.