티스토리 뷰

728x90

 

Notification (알림)

사용자에게 미리 알림을 보내고 앱에서 보내는 정보를 적절한 시기에 제공하기 위해 안드로이드에 앱 외부에서 표시하는 메시지다.

사용자는 알림을 클릭하여 앱을 열거나 알림 자체에서 바로 특정 작업을 실행할 수 있다.

 

 

 

알림 종류

1. status bar 및 알림 목록

첫 번째 사진 처럼 status bar에 아이콘 형태로 notification이 뜰 수 있다.

또한 status bar를 아래로 내리면 알림 목록에 해당 알림이 뜬다.

 

 

2. 헤드업 알림

현재 실행하고 있는 포그라운드 앱 앞에 헤드업 알림이 나타난다.

몇 초 후 사라지고 1번의 경우처럼 status bar와 알림 목록에 표시된다.

 

헤드업 알림이 나타나는 경우는 아래와 같다.

  • 알림의 intent가 fullScreenIntent일 때 (setFullScreenIntent)
  • 알림의 우선순위가 높고, API 25 이하의 기기에서 벨소리 또는 진동일 때
  • API 26 이상의 기기에서 알림 채널(notification channel)의 IMPORTANCE가 HIGH일 때

 

 

3. 잠금 화면

사용자가 설정을 통해 특정 앱의 잠금 화면 알림을 활성화/비활성화 할 수 있다.

잠금 화면 알림은 API 22부터, 활성화/비활성화는 API 26부터 가능하다.

 

 

4. 앱 아이콘 배지

 

API 26부터 앱 아이콘에 알림이 나타날 수 있다. 

앱 아이콘에 알림 점이 나타나고 사용자는 앱 아이콘을 길게 터치하여 해당 알림을 볼 수 있다.

 

 

 

알림 디자인 분석

  1. Small icon: setSmallIcon()을 사용하여 설정한다. (필수)
  2. App name: 시스템에서 제공한다.
  3. Time stamp: 알림이 발생한 시각. 시스템에서 제공한다. setWhen()을 override하거나 setShowWhen(false)를 사용하여 숨길 수 있다.
  4. Large icon: 일반적으로 연락처에만 사용된다. setLargeIcon()을 사용하여 설정한다. 앱 아이콘을 설정하지 않는 것을 권장한다. (선택)
  5. Titel: setContentTitle()을 사용하여 설정한다. (선택)
  6. Text: setContentText()를 사용하여 설정한다. (선택)

 

 

알림 구현하기

기본적인 알림의 종류와 디자인을 살펴봤으니 실제 알림을 구현해보자.

이번 예제에서는 MainActivity에 있는 Button을 클릭하면, 헤드업 알림이 뜨도록 구현할 것이다.

 

1. activity_main.xml

<?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">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        android:id="@+id/btn"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

먼저 MainActivity의 레이아웃을 구성해보자.

기본 Empty Activity에 Button 하나를 생성했다.

 

 

 

2. MyNotification.kt

그 다음 MyNotification이라는 클래스를 만들었다.

여기서는 알림을 보내기 위한 모든 처리를 한다.

물론 MainActivity에서 처리해도 되지만, 의존성을 최소화하기 위해 클래스로 분리했다.

 

class MyNotification(private val context: Context) {

    private var notificationManager: NotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

    init {
        createNotificationChannel()
    }
    
    private fun createNotificationChannel()
    fun deliverNotification() 

    companion object {
        const val CHANNEL_ID = "channel_id"
        const val CHANNEL_NAME = "channel_name"
        const val NOTIFICATION_ID = 0
    }
}
  • context: MyNotification을 생성할 때 context를 전달한다.  알림을 클릭할 때 어떤 activity로 이동할 지 Intent에 담아야 하는데, 이 때 context를 전달해주어야 하기 때문이다.
  • notificationManager: 이 context를 기반으로 NotificationManager를 생성한다. 이 객체를 통해 채널을 등록하고, 알림을 보낸다. 채널을 생성하고 등록하는 함수가 createNotificationChannel(), 알림을 보내는 함수가 deliverNotification()이다.
  • createNotificationChannel(): API 26 이상부터는 알림을 보내기 전에 채널을 무조건 등록해야 하기 때문에 무조건 수행해야 한다. 때문에 Notification을 생성할 때 채널을 등록하도록 init 블록에 넣었다.
  • deliverNotification(): 알림을 보내는 것은 버튼을 누를 때마다 수행되므로 public 함수로 선언했다.
  • 그리고 채널을 생성하고 알림을 보낼 때 ID, NAME 등이 필요하므로 companion class 내의 상수로 선언했다.

 

    init {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            createNotificationChannel()
        }
    }

* 예제 프로젝트에서는 minSdkVersion이 26이상이기 때문에 무조건 채널을 등록해야 한다.

만약 minSdkVerision이 26보다 낮다면 위와 같은 if문을 작성한다.

앱을 실행하는 기기가 26보다 낮다면 채널을 등록하지 않고, 26 이상이면 채널을 등록한다는 의미다.

 

그럼 클래스 내의 함수를 자세히 살펴보자.

 

 

2-1. 채널 생성하고 등록하기

    private fun createNotificationChannel() {
        val notificationChannel =
            NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH)
                .apply {
                    enableVibration(true)
                    description = "description"
                }

        notificationManager.createNotificationChannel(notificationChannel)
    }

NotificationChannel의 생성자로 Id, Name, Importance를 지정한다.

그리고 추가적으로 채널을 맞춤설정하고 싶다면 enableLights(), enableVibration() 등을 호출하면 된다.

맞춤설정하기 위한 함수와 그에 대한 설명은 아래 링크를 참고하자.

https://developer.android.com/reference/android/app/NotificationChannel

 

 

채널의 IMPORTANCE가 어떤 수준이냐에 따라 알림의 종류와 형태가 바뀐다.

중요도가 높을 수록 사용자에게 알림이 더 잘 드러난다.

 

 

2-2. Notification 생성하고 보내기

    fun deliverNotification() {
        val intent = Intent(context, MainActivity::class.java)

        val pendingIntent = PendingIntent.getActivity(
            context,
            NOTIFICATION_ID,
            intent,
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
        )

        val builder = NotificationCompat.Builder(context, CHANNEL_ID)
            .setSmallIcon(R.drawable.ic_icon)
            .setContentTitle("test title")
            .setContentText("test text")
            .setContentIntent(pendingIntent)
            .setAutoCancel(true)
            .setDefaults(NotificationCompat.DEFAULT_ALL)

        notificationManager.notify(NOTIFICATION_ID, builder.build())
    }
  • NotificationCompat.Builder 객체를 통해서 Notification을 생성한다. 여기서 setSmallIcon, setContentTitle 와 같은 함수를 호출해 설정해주면 된다.
  • 사용자가 알림을 클릭했을 때 앱의 어떤 화면으로 이동할지 지정해주려면 setContentIntent()를 사용한다. 이 함수의 인자로는 Intent가 아닌 PendingIntent를 넣어주어야 한다.
  • PendingIntent는 특정 시기(사용자가 알림을 클릭했을 때) Intent를 실행해주는 Intent의 래퍼 클래스다. 자세한 설명은 PendingIntent에 대해 정리한 포스트를 참고하자. https://thdbs523.tistory.com/367
  • 만약 기기가 API 25 이하라서 채널을 등록하지 않은 경우, 알림의 중요도는 Notification의 priority에 따라 결정된다. 이 priority는 NotificationCompat.Builder 객체에 setPriority()를 호출해서 지정한다.
  • notificationManager의 notify 함수를 호출해서 사용자에게 알림을 전송한다.

 

 

3. MainActivity.kt

class MainActivity : AppCompatActivity() {

    private lateinit var myNotification: MyNotification
    private val btn: Button by lazy { findViewById(R.id.btn) }

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

        myNotification = MyNotification(this)
    }

    override fun onResume() {
        super.onResume()

        btn.setOnClickListener {
            myNotification.deliverNotification()
        }
    }
}

액티비티의 버튼을 누를 때마다 알림을 보내야 한다.

즉, MyNotification을 onCreate()에서 생성해 채널을 등록하도록 한다.

그후 onResume()에서 버튼의 클릭 리스너를 지정하는데, MyNotification 인스턴스의 deliverNotification() 함수를 호출해 알림을 보낸다.

 

 

 

4. 실행 결과

MainActivity의 버튼이 눌릴 때마다 알림이 전송된다.

채널의 중요도를 HIGH로 설정했기 때문에 헤드업 알림이 뜨는 것을 확인할 수 있다.

 

 

 

 

예전에는 제대로 이해하지 못하고 무작정 다른 사람 코드만 복붙했던 것 같은데,

이번 기회에 확실히 개념을 이해할 수 있었다.

다음에는 AlarmManager를 활용해서 정해진 시간에 주기적으로 알림을 보내는 방법을 포스팅 해야겠다.

 

 

참조 

https://developer.android.com/training/notify-user/build-notification?hl=ko 

https://developer.android.com/develop/ui/views/notifications

728x90
250x250
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
글 보관함