[Android / Kotlin] Notification

Subeen·2023년 3월 24일
0

Android

목록 보기
16/73
post-thumbnail

📍 지원 라이브러리 추가

모듈 수준 build.gradle 파일에 다음 종속 항목이 포함되어 있는지 확인해야 한다.

dependencies {
        implementation "com.android.support:support-compat:28.0.0"
    }

📍 권한 요청 (Android 13)

💡 Android 13(API 수준 33)에서는 앱에서 예외 없는 알림을 보내기 위한 새로운 런타임 권한 POST_NOTIFICATIONS를 도입했다.

  • AndroidManifest.xml
    앱의 매니페스트 파일에서 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())
        }
    }

📍 Drawable을 Bitmap으로 변환

    private fun convertBitmap(): Bitmap {
        val drawable = getDrawable(R.drawable.notification)
        val bitmapDrawable = drawable as BitmapDrawable
        val bitmap = bitmapDrawable.bitmap

        return bitmap
    }

📍 전체 코드

👀 결과 동영상

👩🏻‍💻 버튼을 클릭 했을 때 알림을 만드는 예제

  • build.gradle (:app)
android {
    buildFeatures {
        dataBinding true
        viewBinding true
    }
}
  • activity_main.xml
<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>
  • MainActivity.kt
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
    }

}
profile
개발 공부 기록 🌱

0개의 댓글