Debbi Story

Custom Notification bar 만들기 본문

안드로이드/Tip

Custom Notification bar 만들기

Debbi 2020. 10. 28. 02:11
728x90

 

일반적인 notification은 swipe시 사라지지만 

swipe해도 사라지지 않고 계속 고정으로 떠있는 커스텀 notification은 만들어 보겠습니다.

 

val contentIntent = Intent(context, MainActivity::class.java)
contentIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
val contentPendingIntent = PendingIntent.getActivity(
    context,
    123,
    contentIntent,
    PendingIntent.FLAG_UPDATE_CURRENT
)

val refreshIntent = Intent(context, NotifyActionReceiver::class.java)
refreshIntent.action = "REFRESH"
val refreshPendingIntent = PendingIntent.getBroadcast(context, 123, refreshIntent, PendingIntent.FLAG_UPDATE_CURRENT)

val closeIntent = Intent(context, NotifyActionReceiver::class.java)
closeIntent.action = "CLOSE"
closeIntent.putExtra("ID", notiBarID)
val closePendingIntent = PendingIntent.getBroadcast(context, 123, closeIntent, PendingIntent.FLAG_UPDATE_CURRENT)

val remoteViews = RemoteViews(context.packageName, R.layout.item_noti_bar)
remoteViews.setTextViewText(R.id.notiBar_tv_01, "noti_text")
remoteViews.setOnClickPendingIntent(R.id.notiBar_btn_refresh, refreshPendingIntent)
remoteViews.setOnClickPendingIntent(R.id.notiBar_btn_close, closePendingIntent)

val builder =
    NotificationCompat.Builder(context, "CHANNEL_ID")
        .setSmallIcon(R.drawable.ic_stat_seven_todo_noti)
        //.setStyle(NotificationCompat.DecoratedCustomViewStyle())
        .setColor(context.resources.getColor(R.color.colorNoti, null))
        .setCustomContentView(remoteViews)
        //.setCustomBigContentView(bigRemoteViews)
        .setContentIntent(contentPendingIntent)
        .setPriority(NotificationCompat.PRIORITY_HIGH)
        .setDefaults(NotificationCompat.DEFAULT_ALL)
        .setOngoing(true)
        
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.notify(notiBarID, builder.build())

 

먼저 contentPendingIntent는 notification을 터치했을때 실행할 intent를 정의한것이고

Notification Builder에 .setContentIntent(contentPendingIntent) 여기에 해당한다.

 

refreshPendingIntent 와 closePendingIntent는 커스텀으로 만든 버튼들의 클릭 이벤트로 수행 할 intent를 정의했다.

 

가장 중요한 것은 RemoteViews(context.packageName, R.layout.item_noti_bar) 로 커스텀 레이아웃을 생성하는 부분이다.

xml에 원하는대로 ui를 배치시면된다. 그런데 androidx로 시작하는 widget을 사용하면 오류가 발생한다. 예를 들면 androidx.appcompat.widget.AppCompatTextView 그래서 기본 TextView를 사용했고 뷰들의 속성값으로 어떤것을 추가하면 오류가 생겼던 걸로 기억한다..

그리고 만든 각각의 뷰 id를 넣고 값을 세팅해준다. 마찬가지로 Notification Builder에 .setCustomContentView(remoteViews) RemoteView를 넣어준다. 

그리고! .setOngoing(true) true를 주면 swipe해도 사라지지 않는다.

이렇게 하면 커스텀 Notification을 간단하게 만들수가 있고 Notification을 아래로 swipe해 확장시키고 싶다면 layout을 하나 더 만들고

.setStyle(NotificationCompat.DecoratedCustomViewStyle())

.setCustomBigContentView(bigRemoteViews)

해보지는 않았지만 이렇게 추가해주면 될 것 같다.

 

그럼 이 Notification을 어떻게 없애지? 앱 정보에가서 앱을 강제 중지 시키거나 알림 설정에서 알림 받기를 해제하면 사라진다.

하지만 X 버튼을 눌러 사라지게 하고싶다면 위처럼 layout에 x버튼을 만들고 closePendingIntent와 NotifyActionReceiver를 만들었다.

 

class NotifyActionReceiver : BaseBroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        super.onReceive(context, intent)

        when(intent.action) {
            
            "REFRESH" -> {
				//show notification
            }
            "CLOSE" -> {
                val id = intent.getIntExtra("ID", 0)
                val s = Context.NOTIFICATION_SERVICE
                val nm = context.getSystemService(s) as NotificationManager
                nm.cancel(id)
  
            }
        }
    }
}

 

이런식으로 BaseBroadcastReceiver를 만들었고 intent에 notiBarID를 넘겨주어 같은 id 이어야만 noti가 사라진다.

그릭고 추가로 이미 떠있는 notification에 내용을 변경해주고 싶어서 refreshPendingIntent도 만들었고 위에서 처음에 했던 Notification Builder 생성하는 부분처럼 똑같이 텍스트뷰 등 변경하고싶은 값으로 바꾸어 새로 notify해주면 refresh 된 것 처럼 구현이 된다.

이렇게 하는 방식이 정확한 것이 아닐수 있어 참고만 부탁드립니다.