#1 ๊ฐ์
์๋ฆผ ๊ฐ์ | Views | Android Developers
์ด ํ์ด์ง๋ Cloud Translation API๋ฅผ ํตํด ๋ฒ์ญ๋์์ต๋๋ค. ์๋ฆผ ๊ฐ์ ์ปฌ๋ ์ ์ ์ฌ์ฉํด ์ ๋ฆฌํ๊ธฐ ๋ด ํ๊ฒฝ์ค์ ์ ๊ธฐ์ค์ผ๋ก ์ฝํ ์ธ ๋ฅผ ์ ์ฅํ๊ณ ๋ถ๋ฅํ์ธ์. ์๋ฆผ์ ์ฌ์ฉ์์๊ฒ ๋ฆฌ๋ง์ธ๋, ๋ค๋ฅธ ์ฌ๋๊ณผ
developer.android.com
์ฑ์๊ฒ ์์ด ์๋ฆผ(Notifications)๋ ๋นผ๋์ ์ ์๋ ๊ตฌ์ฑ ์์๋ค. ์๋ฆผ์ ๊ธฐ์ด์ ์ผ๋ก ๊ตฌํํด๋ณธ๋ค.
#2 SDK, ๊ถํ, View ์ค์
#2-1 ์ต์ SDK ์ค์

Minimum SDK๋ฅผ API ๊ธฐ์ค 26 ์ด์์ผ๋ก ์ค์ ํ๋ค. Notifications ๋๋ถ๋ถ ๊ธฐ๋ฅ์ ์ต์ ์๊ตฌ API๊ฐ 26์ด๊ธฐ ๋๋ฌธ์ด๋ค.
#2-2 AndroidManifest.xml์์ ์๋ฆผ ๊ถํ ์ค์
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<application
...
</application>
</manifest>
์๋ฆผ ๋ฐ์์ ๋ํ ๊ถํ์ ํ์ฉํด์ค๋ค.
#2-3 View ๊ตฌํ
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="MainActivity"
android:textSize="40dp"
app:layout_constraintBottom_toTopOf="@id/button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Trigger Notification"
android:textSize="30dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
</androidx.constraintlayout.widget.ConstraintLayout>
TextView ํ๋์ Button ํ๋๊ฐ ์๋ ๊ฐ๋จํ View๋ฅผ ๊ตฌ์ฑํ๋ค.
#3 MainActivity.kt ๊ตฌํ
#3-1 NotificationManager ํ ๋น
// package com.example.notificationsbasics
...
class MainActivity : AppCompatActivity() {
private var notificationManager: NotificationManager? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val button = findViewById<Button>(R.id.button)
notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
}
}
๊ทธ ๋ค์์ ์๋ฆผ์ ๋ฐ์์ํค๋ ํด๋์ค์ธ NotificationManager์ ์ธ์คํด์ค๋ฅผ ํ ๋นํ๋ค. NotificationManager๋ System Service์ ์ผ์ข ์ผ๋ก, Context.getSystemService(name: String)๋ก ์ธ์คํด์ค๋ฅผ ๊ฐ์ ธ์ฌ ์ ์๋ค. ํ๋กํผํฐ notificationManager๋ฅผ val์ด ์๋ var๋ก ์ ์ธํ๋ ์ด์ ๋, ์กํฐ๋นํฐ์ ์๋ช ์ฃผ๊ธฐ ๋์ onCreate()๊ฐ ์ฌ๋ฌ ๋ฒ ์คํ๋ ์ฌ์ง๊ฐ ์๊ณ , ๋ฐ๋ผ์ ๊ทธ ๋๋ง๋ค getSystemService(name: String)๊ฐ ์ฌํ ๋น๋ ๊ฐ๋ฅ์ฑ ๋ํ ์๊ธฐ๊ธฐ ๋๋ฌธ์ด๋ค.
#3-2 NotificationChannel
...
class MainActivity : AppCompatActivity() {
private var notificationManager: NotificationManager? = null
private val channelId = "com.example.notificationsbasics.channel1"
override fun onCreate(savedInstanceState: Bundle?) {
...
notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
createNotificationChannel(channelId, "My Channel", "It's my channel")
}
private fun createNotificationChannel(id: String, name: String, channelDescription: String) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // ์ซ์ 0์ด ์๋๋ผ Oreo์ ์ฒซ ๊ธ์์ธ ์ํ๋ฒณ ๋๋ฌธ์ O๋ค.
val importance = NotificationManager.IMPORTANCE_HIGH
val channel = NotificationChannel(id, name, importance).apply {
description = channelDescription
}
notificationManager?.createNotificationChannel(channel)
}
}
}
๋ณธ๊ฒฉ์ ์ผ๋ก Notifications ์ฝ๋๋ฅผ ์งค ๋ ์ฐ์ ์ ์ผ๋ก ํด์ผํ๋ ์์ ์ ๋ฐ๋ก NotificationChannel์ ํ ๋นํ๋ ๊ฒ์ด๋ค. NotificationChannel ๊ฐ์ฒด์ ์กด์ฌ ์ด์ ๋ ์๋ฆผ์ ์นดํ ๊ณ ๋ฆฌํ๋ค. ๋ฉ์ ์ ์ฑ์ ์๋ก ๋ค๋ฉด, ๋ฉ์์ง ๋์ฐฉ ์๋ฆผ, ๊ทธ๋ฃน ์ฑํ ๋ฐฉ ์ด๋ ์๋ฆผ, ์น๊ตฌ ์ถ๊ฐ ์๋ฆผ ๋ฑ์ ์๋ก ๊ตฌ๋ถ๋๋ ๋ชฉ์ ๊ณผ ์ค์๋๋ฅผ ์ง๋๋ค. NotificationChannel์ด ๋ฐ๋ก ๊ทธ๋ฌํ ์นดํ ๊ณ ๋ฆฌํ๋ฅผ ์ํํ๋ค.
ํ๋ก๊ทธ๋๋จธ ์ ์ฅ์์ ์นดํ ๊ณ ๋ฆฌ๋ณ๋ก ๋๋๋ ์๋ฆผ๋ง๋ค ์๋ฆผ ์คํ์ผ, ์ค์๋ ๋ฑ์ ์ผ๊ด์ ์ผ๋ก ์ค์ ํด์ค ์ ์๋ค๋ ์ด์ ์ด ์๋ค. ์ฌ์ฉ์ ์ ์ฅ์์๋ ์ ์ ๋ ์ฌ์ฉ์ ๊ฒฝํ์ ์ ์ฌํ๊ณ , ํน์ ์ ํ์ ์นดํ ๊ณ ๋ฆฌ์ ๋ํ ์๋ฆผ์ ๋ช ์์ ์ผ๋ก ์์ ๊ฑฐ๋ถํ๊ธฐ ํธ๋ฆฌํ๊ฒ ๋ง๋ค์ด์ค๋ค.
'์ฌ์ฉ์ ์ ์ ์๋ฆผ ์ฑ๋'์ด๋ผ๋ ๊ฐ๋ ์์ฒด๊ฐ API 26๋ถํฐ ์๊ฒจ๋ฌ๊ธฐ์ API 26(์๋๋ก์ด๋ Oreo)๋ถํฐ NotificationChannel์ด ์ง์๋๋ค. API๊ฐ 26 ๋ฏธ๋ง์ธ ์๋๋ก์ด๋ OS์์๋ if๋ฌธ์ ์ํด createNotificationChannel()๊ฐ ์ํ๋์ง ์์ผ๋ฉฐ, ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์ค์ ๋ ์ฑ๋์ ์๋ฆผ์ด ์์ ๋๋ค.
#3-3 NotificationManager.notify() ๊ตฌํ
...
class MainActivity : AppCompatActivity() {
...
override fun onCreate(savedInstanceState: Bundle?) {
...
notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
createNotificationChannel(channelId, "My Channel", "It's my channel")
button.setOnClickListener {
displayNotification()
}
}
private fun displayNotification() {
val notificationId = 777 // ์๋ฆผ ์ฑ๋ Id์๋ ๋ ๋ค๋ฅธ ์๋ฆผ ํ๋ํ๋์ Id. ๋์ผํ Id์ ์๋ฆผ์ด ์ํ๋ฐ์ ์์ ๋, ๊ฐ์ Id์ธ ์๋ฆผ์ ๋ฐ์์ํค๋ฉด, ์๋ ์๋ ์๋ฆผ์ด ์ต์ ์๋ฆผ์ผ๋ก ๊ฐ์๋ผ์์ง๋ค.
val notification = NotificationCompat.Builder(this@MainActivity, channelId).apply {
setContentTitle("My Notification Title") // ์ํ๋ฐ ๋ด๋ฆฌ๋ฉด ํ๋ฉด์ ๋ณด์ผ ์๋ฆผ ์ ๋ชฉ
setContentText("It's my notification") // ์ํ๋ฐ ๋ด๋ฆฌ๋ฉด ํ๋ฉด์ ๋ณด์ผ ์๋ฆผ ๋ณธ๋ฌธ
setSmallIcon(android.R.drawable.ic_dialog_info) // ์๋ฆผ ์์ด์ฝ ์ค์
setAutoCancel(true) // ์ํ๋ฐ์์ ์๋ฆผ ํด๋ฆญ ์, ์๋ฆผ์ด ์ฌ๋ผ์ง๊ฒ ๋ง๋๋ ์ต์
(ํ์ง๋ง, PendingIntent๊ฐ ์์ผ๋ฉด ์ต์
์ ์ฉ ์๋จ)
setPriority(NotificationCompat.PRIORITY_HIGH) // API 26 ๋ฏธ๋ง์ ์ํ ์๋ฆผ ์ค์๋ ์ต์
. API 26 ์ด์๋ถํฐ๋ NotificationChannel์ ํ ๋นํ ์๋ฆผ ์ค์๋๊ฐ ์ฐ์ ์๋๋ค.
}.build()
notificationManager?.notify(notificationId, notification)
}
private fun createNotificationChannel(id: String, name: String, channelDescription: String) {
...
}
}
๋ฒํผ์ ๋๋ฅด๋ฉด ์๋ฆผ์ด ์ํ๋ฐ์ ๊ฒ์๋๋๋ก ๋ง๋ ๋ค. ์ฌ๊ธฐ์๋ ์๋ฆผ Id๋ฅผ ํ์ด์ ์์ธ 777๋ก ์ ํด์ฃผ์์ผ๋, ์ค์ ์ฑ์ ๊ฐ๋ฐํ ๋๋ ์ฒด๊ณ์ ์ธ ๊ท์น์ ์ ํด๋๊ณ ์ ์คํ๊ฒ ์ค์ ํด์ฃผ์ด์ผ ํ ๊ฒ์ด๋ค. NotificationManager.notify()์ ๋ ๋ฒ์งธ ์ธ์์ธ Notification์ AndroidX์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ํ๋ NotificationCompat์ ๋น๋ ํด๋์ค NotificationCompat.Builder๋ฅผ ํตํด ์์ฑํ๋ค. ๋ฉ์๋ ์ฒด์ด๋์ผ๋ก NotificationCompat.Builder ๊ฐ์ฒด๋ฅผ ์ฐ์์ ์ผ๋ก ๋ง๋ค๊ณ , ํด๋น ๊ฐ์ฒด๋ฅผ build()ํ์ฌ Notification ๊ฐ์ฒด notification์ ๋ง๋ค๊ณ ์๋ ๋ชจ์ต์ ๋ณผ ์ ์๋ค.
๋ฉ์๋ ์ฒด์ด๋ ๊ตฌ๋ฌธ ์ค์ ์๋ autoCancel์ true๋ก ์ค์ ํด๋, PendingIntent๊ฐ ์๋ค๋ฉด ์ํ๋ฐ์์ ์๋ฆผ์ ํด๋ฆญํด๋ ์๋ฆผ์ด ์ฌ๋ผ์ง์ง ์๋๋ค. ๋ค์ ๊ฒ์๊ธ์์ NotificationCompat.Builder.setContentIntent(intent: PendingIntent?)๋ฅผ ํตํด PendingIntent๋ฅผ ํ ๋นํด๋ณด๊ฒ ๋ค.
#4 ์๋ ํ์ธ

๋ง์ฝ ๋ฒํผ์ ๋๋ฌ๋ ์๋ฆผ์ด ๋จ์ง ์๋๋ค๋ฉด, ์ค์น๋ ์ฑ์ ์๋ฆผ ๊ถํ์ด ์ฐจ๋จ๋์ง๋ ์์๋์ง ํ์ธํด๋ณด์. ๊ธฐ๋ณธ๊ฐ ์ค์ ์ด ์ฐจ๋จ์ธ ๊ฒฝ์ฐ๊ฐ ์๋ค.
#5 ์์ฑ๋ ์ฑ
android-practice/notifications/NotificationsBasics at master ยท Kanmanemone/android-practice
Contribute to Kanmanemone/android-practice development by creating an account on GitHub.
github.com
#6 ์ด์ด์ง๋ ๊ธ
[Android] Notifications - PendingIntent
#1 ์ด์ ๊ธ [Android] Notifications - ๊ธฐ์ด#1 ๊ฐ์ ์๋ฆผ ๊ฐ์ | Views | Android Developers์ด ํ์ด์ง๋ Cloud Translation API๋ฅผ ํตํด ๋ฒ์ญ๋์์ต๋๋ค. ์๋ฆผ ๊ฐ์ ์ปฌ๋ ์ ์ ์ฌ์ฉํด ์ ๋ฆฌํ๊ธฐ ๋ด ํ๊ฒฝ์ค์ ์ ๊ธฐ์ค
kenel.tistory.com
๋ณธ ๊ฒ์๊ธ์ ๊ธฐ๋ฐ์ผ๋ก ์๋ฆผ ํด๋ฆญ ์์ ๋์์ ๊ตฌํํด๋ณธ๋ค.
'๊นจ์ ๊ฐ๋ ๐ > Android' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Android] Notifications - Action ๋ฒํผ ํด๋ฆญ ์ ์๋ฆผ Cancel (0) | 2024.06.14 |
---|---|
[Android] Notifications - PendingIntent (0) | 2024.06.12 |
[Android] Retrofit - Post (0) | 2024.06.11 |
[Android] Retrofit - Logging, Timeout ๊ด๋ฆฌ (Interceptor) (0) | 2024.06.11 |
[Android] Retrofit - MVVM ๊ตฌ์กฐ (0) | 2024.06.05 |