Android 알림 띄우기

timothy jeong·2021년 11월 5일
0

Android with Kotlin

목록 보기
18/69

앱의 상태바(베터리, 네트워크, 시간)에 앱의 정보를 출력하는 걸을 알림(notification) 이라고 한다. 원래 상태바는 안드로이드 시스템이 관리하는 곳으로 앱이 직접 제어할 수 없다. 그러므로 앱은 시스템에 의뢰하는 (시스템 콜 같은건가?) 형태로 알림을 띄우게 된다. 따라서 앱의 화면을 구성하거나 사용자 이벤트를 처리하는 프로그래밍과는 구조가 다르며, 알림을 위해 제공하는 API 를 이용해야 한다.

알림 채널

알림은 NotificationManager의 notify() 함수로 발생한다. notify() 함수에는 NotificationCompat.Builder 가 만들어주는 Notification 객체를 대입하며, 이 객체에는 알림 정보가 저장된다. 그런데 NotificationCompat.Builder 가 create 를 하기 위해서는 NotificationChannel 정보를 대입해 줘야한다.

이런 모습인 것이다.

val notification: Notification = 
    NotificationCompat.Builder(this, NotificationChannel).create()

NotificationManager.notify(notification) // 알림 요청

NotificationCompat.Builder 를 만드는 방법이 API level 26 을 기점으로 변하였다. 이전에는 Builder(context: Context!) 였지만, 26 부터는 Builder(context: Context, channelld: String!) 이 되었다. 즉 NotificationChannel 을 만들고 이 식별값을 빌더의 생성자 매개변수에 지정해 줘야한다.

이 NotificationChannel 채널은 앱의 알림의 종류를 구분하는 것이다. 만약 알람 채널에 대한 구분이 없는 상태에서 유저가 알람을 끄면 중요한 알림들 (베터리가 없다 등)까지 모두 유저에게 전달 되지 않게된다. 하지만 API 26 부터는 앱별로 알람을 설정할 수 있음로 이런 걱정이 없다.

NotificationChannel 생성자는 다음과 같다. 식별자(id) 와 채널 이름(name) 그리고 중요도(importance) 를 요구한다.

NotificationChannel(id: String!, name: CharSequence!, importance: Int)

중요도는 상수를 제공하고 있다.

중요도 상수설명
NotificationManager.IMPORTANCE_HIGH긴급 상황으로 알림음이 울리며 헤드업으로 표시
NotificationManager.IMPORTANCE_DEFAULT높은 중요도이며 알림음이 울림
NotificationManager.IMPORTANCE_LOW중간 중요도이며 알림음이 울리지 않음
NotificationManager.IMPORTANCE_MIN낮은 중요도이며 알림음도 없고 상태 바에도 표시되지 않음

채널의 각종 정보는 하수나 프로퍼티로 설정할 수 있다.

setDescription(String) : 채널의 설명 문자열
setShowBadge(Boolean) : 홈 화면의 아이콘에 배지 아이콘 출력 여부
setSound(sound: Uri, audioAttributes: AudioAttributes) : 알림음 재생
enableLight(Boolean) 불빛 표시 여부
setLightColor(argb: Int) : 불빛을 표시한다면 불빛의 생삭
enableVibration(vibration: Boolean) : 진동 여부
setVibrationPatter(LongArray!) : 진동을 울린다면 진동의 패턴

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val button = findViewById<Button>(R.id.button)

        val manager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
        val notificationBuilder: NotificationCompat.Builder = getNotificationBuilder(this, manager)
        
        button.setOnClickListener {}
    }
}

fun getNotificationBuilder(context: Context, manager: NotificationManager) : NotificationCompat.Builder {

    if (Build.VERSION.SDK_INT >= 26) {

        // channel 기본 정보 설정
        val channelId = "one-channel"
        val channelName = "My Channel One"
        val channel = NotificationChannel(
            channelId,
            channelName,
            NotificationManager.IMPORTANCE_HIGH
        )

        // 추가적인 channel 설정
        channel.description = "My Channel One DESC"
        channel.setShowBadge(true)
        val uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
        val audioAttributes = AudioAttributes.Builder()
            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
            .setUsage(AudioAttributes.USAGE_ALARM)
            .build()
        channel.setSound(uri, audioAttributes)
        channel.enableLights(true)
        channel.enableVibration(true)
        channel.vibrationPattern = longArrayOf(100, 200, 100, 200)

        // 설정한 채널을 NotificationManager 에 등록
        manager.createNotificationChannel(channel)

        return NotificationCompat.Builder(context, channelId)
    }
    return NotificationCompat.Builder(context)
}

알림 객체

이상의 코드로 Notification.Builder 를 얻을 수 있다. 이 Builder 를 이용해서 Notification 를 얻어야 한다. 이 Notification 객체에 출력할 이미지, 문자열 등의 정보를 담는다.

상태바에 표시될 이미지는 setSmallIcon(drawable) 로 설정하며, 시각은 setWhen (long when), setContentTitle(String), setContentText(String) 를 이용해서 알림의 내용을 구성한다.

마지막으로 manager.notify(id, Notification) 을 하면 알람이 발송된다.

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val button = findViewById<Button>(R.id.button)

        val manager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
        val notificationBuilder: NotificationCompat.Builder = getNotificationBuilder(this, manager)
        notificationBuilder.setSmallIcon(R.drawable.ic_launcher_foreground)
        notificationBuilder.setWhen(System.currentTimeMillis())
        notificationBuilder.setContentTitle("hello")
        notificationBuilder.setContentText("This is Notification")

        button.setOnClickListener {manager.notify(11, notificationBuilder.build())}
    }
}

지정된 id 는 개발자가 임의로 지정하는 것으로 알림을 코드에서 취소할때 사용된다. 이때 cancel() 함수를 이용하며 매개변수로 취소할 알림의 식별자 값을 전달한다.사용자가 알림을 터치하면 이벤트가 발생할 수 있으며 이때 알림은 화면에서 자동으로 사라진다. 또한 사용자가 스와이프 하여 알림을 지울 수도 있다. 이렇게 터치나 스와이프를 해도 알람이 사라지지 않게 하려면 빌더의 세터 함수로 지정해야한다.

builder.setAutoCancel(false)
builder.setOngoing(true)

setAutoCancel(false) 로 지정하면 알림을 터치할 때 이벤트는 발생하지만 알림이 사라지지는 않는다. 또한 setOngoing(true) 로 지정하면 사용자가 알림을 스와이프해도 사라지지 않는다. 이상 두개를 모두 설정했다면 사용자가 알림을 취소할 수 없으므로 결국에는 코드에서 cancel() 함수로 취소를 해야한다.

profile
개발자

0개의 댓글