모듈 수준 build.gradle 파일에 다음 종속 항목이 포함되어 있는지 확인해야 한다.
dependencies {
implementation "com.android.support:support-compat:28.0.0"
}
💡 Android 13(API 수준 33)에서는 앱에서 예외 없는 알림을 보내기 위한 새로운 런타임 권한 POST_NOTIFICATIONS를 도입했다.
<manifest ...>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<application ...>
...
</application>
</manifest>
Android API 수준이 33 이상일 경우에만 권한의 허용 여부를 확인한다.
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val PERMISSION_REQUEST_CODE = 5000
private fun permissionCheck() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
val permissionCheck = ContextCompat.checkSelfPermission(
this,
android.Manifest.permission.POST_NOTIFICATIONS
)
if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(
this,
arrayOf(android.Manifest.permission.POST_NOTIFICATIONS),
PERMISSION_REQUEST_CODE
)
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
permissionCheck()
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when (requestCode) {
PERMISSION_REQUEST_CODE -> {
if (grantResults.isEmpty() || grantResults[0] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(applicationContext, "Permission is denied", Toast.LENGTH_SHORT)
.show()
} else {
Toast.makeText(applicationContext, "Permission is granted", Toast.LENGTH_SHORT)
.show()
}
}
}
}
}
💡 Android 8.0 이상에서 알림을 제공하려면 NofiticationChannel 인스턴스를 createNotificationChannel() 에 전달하여 앱의 알림 채널을 시스템에 등록해야 한다.
private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val name = "name"
val descriptionText = "description"
val importance = NotificationManager.IMPORTANCE_DEFAULT
val channel = NotificationChannel("TestChannel", name, importance).apply {
description = descriptionText
}
val notificationManager: NotificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
}
가장 기본적이고 간단한 형태의 알림에는 아이콘, 제목 및 소량의 콘텐츠 텍스트가 표시된다.
NotificationCompat.Builder 객체를 사용하여 알림 콘텐츠와 채널을 설정한다.
- setSmallIcon() : 작은 아이콘
- setContentTitle() : 제목
- setContentText() : 본문 텍스트
- setPriority() : 알림 우선순위
@SuppressLint("MissingPermission")
private fun sendNotification() {
val builder = NotificationCompat.Builder(this, "TestChannel")
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
.setContentText("Hello World!")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
// 알림 표시
with(NotificationManagerCompat.from(this)) {
notify(1, builder.build())
}
}
📌 큰 이미지 추가
알림에 이미지를 추가하려면 NotificationCompat.BigPictureStyle의 인스턴스를 setStyle()에 전달한다.
알림이 접힌 상태일 때만 이미지를 미리보기 이미지로 표시하려면 setLargeIcon()을 호출하여 이미지를 전달한 후 BigPictureStyle.bigLargeIcon()도 호출하여 null을 전달한다.
@SuppressLint("MissingPermission")
private fun sendExpansionNotification() {
val notification = NotificationCompat.Builder(this, "TestChannel")
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My expansion notification")
.setContentText("Hello World!")
.setLargeIcon(convertBitmap())
.setStyle(NotificationCompat.BigPictureStyle()
.bigPicture(convertBitmap())
.bigLargeIcon(null))
with(NotificationManagerCompat.from(this)) {
notify(1, notification.build())
}
}
private fun convertBitmap(): Bitmap {
val drawable = getDrawable(R.drawable.notification)
val bitmapDrawable = drawable as BitmapDrawable
val bitmap = bitmapDrawable.bitmap
return bitmap
}
android {
buildFeatures {
dataBinding true
viewBinding true
}
}
<layout>
<LinearLayout 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"
android:gravity="center"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/btnNotification"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="#e2cce7"
android:text="Basic Notification"
android:textColor="@color/white" />
<Button
android:id="@+id/btnExpansionNotification"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:background="#e2cce7"
android:text="Expansion Notification"
android:textColor="@color/white" />
</LinearLayout>
</layout>
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val PERMISSION_REQUEST_CODE = 5000
private fun permissionCheck() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
val permissionCheck = ContextCompat.checkSelfPermission(
this,
android.Manifest.permission.POST_NOTIFICATIONS
)
if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(
this,
arrayOf(android.Manifest.permission.POST_NOTIFICATIONS),
PERMISSION_REQUEST_CODE
)
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
permissionCheck()
createNotificationChannel()
binding.btnNotification.setOnClickListener {
sendNotification()
}
binding.btnExpansionNotification.setOnClickListener {
sendExpansionNotification()
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when (requestCode) {
PERMISSION_REQUEST_CODE -> {
if (grantResults.isEmpty() || grantResults[0] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(applicationContext, "Permission is denied", Toast.LENGTH_SHORT)
.show()
} else {
Toast.makeText(applicationContext, "Permission is granted", Toast.LENGTH_SHORT)
.show()
}
}
}
}
private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val name = "name"
val descriptionText = "description"
val importance = NotificationManager.IMPORTANCE_DEFAULT
val channel = NotificationChannel("TestChannel", name, importance).apply {
description = descriptionText
}
val notificationManager: NotificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
}
@SuppressLint("MissingPermission")
private fun sendNotification() {
val builder = NotificationCompat.Builder(this, "TestChannel")
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
.setContentText("Hello World!")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
// 알림 표시
with(NotificationManagerCompat.from(this)) {
notify(1, builder.build())
}
}
@SuppressLint("MissingPermission")
private fun sendExpansionNotification() {
val notification = NotificationCompat.Builder(this, "TestChannel")
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My expansion notification")
.setContentText("Hello World!")
.setLargeIcon(convertBitmap())
.setStyle(NotificationCompat.BigPictureStyle()
.bigPicture(convertBitmap())
.bigLargeIcon(null))
with(NotificationManagerCompat.from(this)) {
notify(1, notification.build())
}
}
private fun convertBitmap(): Bitmap {
val drawable = getDrawable(R.drawable.notification)
val bitmapDrawable = drawable as BitmapDrawable
val bitmap = bitmapDrawable.bitmap
return bitmap
}
}