Android/Side Projects

푸쉬 알림 수신기 앱 개발하기

화요밍 2022. 2. 5. 18:32
728x90
반응형
Side Project - Push-Notification-Receiver
FCM(Firebase Cloud Messaging)을 통해 보낸 메세지를 수신하는 앱을 구현한 프로젝트

 

 

GitHub - hwayeon351/Push-Notification-Reciever

Contribute to hwayeon351/Push-Notification-Reciever development by creating an account on GitHub.

github.com


학습 회고

오늘은 알림 수신기 앱을 완성했다.

Normal 타입과 Expandable 타입, Custom 타입의 알림을 만들고, 수신 받은 알림을 클릭해 앱을 실행하는 기능을 추가했다.


오늘 공부한 내용

  • 알림 방식

안드로이드 기기에 알림이 표시되는 형식은 3가지가 있다.

1. 상태 표시줄과 알림 창

상태 표시줄 알림
알림 창 알림

상태 표시줄과 알림 창에 표시된 알림은 앱이나 사용자가 닫을 때까지 알림 창에 표시된다.

 

 

2. 헤드업 알림

플로팅 창에 알림을 간단히 표시한다. 사용자가 즉시 알아야하는 중요한 알림에 사용되고 기기가 잠금 해제 될 때만 표시된다.

헤드업 알림

헤드업 알림은 앱에서 알림을 보낸 순간 표시되고 잠시 후에 사라지지만 알림 창에는 계속 표시된다.

 

 

3. 잠금 화면

Android 5.0부터는 잠금 화면에 알림을 표시할 수 있다.

사용자는 시스템 설정을 통해 잠금 화면 알림 사용 중지 옵션과 잠금 화면 알림에 표시되는 세부정보의 수준을 선택할 수 있다.

Android 8.0부터 사용자는 각 알림 채널에서 잠금화면 알림을 사용/사용중지를 선택할 수 있다.

잠금 화면 알림

 

4. 앱 아이콘 배지 알림

Android 8.0 이상을 실행하는 기기는 앱 런처 아이콘 위에 배지로 알림을 표시한다.

사용자는 앱 아이콘을 길게 눌러 해당 앱의 알림을 볼수 있고, 알림을 닫거나 알림을 통해 작업을 실행할 수 있다.

앱 아이콘 배지 알림

 

 

 

  • 알림 구성
  • 기본 알림 Normal Notification

알림 디자인은 시스템 템플릿에 의해 결정된다. 앱에서는 탬플릿의 각 부분에 해당하는 콘텐츠만 정의할 수 있다.

  1. 작은 아이콘: 필수 구성요소이며 setSmallIcon()을 통해 설정할 수 있다.
  2. 앱 이름: 시스템에서 제공한다.
  3. 타임스탬프: 시스템에서 제공하지만 setWhen()을 사용해서 재정희하거나 setShowWhen(false)로 숨길 수 있다.
  4. 큰 아이콘: 선택 사항으로 setLargeIcon()을 사용해서 설정할 수 있다.
  5. 제목: 선택사항으로 setContentTitle()을 통해 설정할 수 있다.
  6. 텍스트: 선택사항으로 setContentText()를 통해 설정할 수 있다.

 

알림을 만드려면 NotificationCompat.Builder 객체를 사용해서 알림 콘텐츠와 채널을 설정해야 한다.

val notificationBuilder = NotificationCompat.Builder(this, CHANNEL_ID)
    .setSmallIcon(R.drawable.ic_baseline_notifications_24)
    .setContentTitle(title)
    .setContentText(content)
    .setPriority(NotificationCompat.PRIORITY_DEFAULT)
    .setContentIntent(pendingIntent)
    .setAutoCancel(true)

 

 

  • 커스텀 알림 Custom Notification

모든 기기에서 호환성을 보장하기 위해 시스템 템플릿을 사용하는 것이 좋지만 커스텀 알림 레이아웃을 만들어서 적용할 수 있다.

알림에 NotificationCompat.DecoratedCustomViewStyle을 적용해서 맞춤 레이아웃을 적용할 수 있다.

  1. NotificationCompat.Builder로 기본 알림을 빌드한다.
  2. setStyle()을 호출해서 NotificationCompat.DecoratedCustomViewStyle 인스턴스를 전달한다.
  3. 레이아웃을 RemoteViews의 인스턴스로 확장한다.
  4. setCustomContentView()를 호출해서 알림의 레이아웃을 설정한다. setCustomBigContentView()를 호출해서 확장 알림에 맞춤 레이아웃을 설정할 수도 있다.
val notificationBuilder = NotificationCompat.Builder(this, CHANNEL_ID)
    .setSmallIcon(R.drawable.ic_baseline_notifications_24)
    .setContentTitle(title)
    .setContentText(content)
    .setPriority(NotificationCompat.PRIORITY_DEFAULT)
    .setContentIntent(pendingIntent)
    .setAutoCancel(true)

NotificationType.CUSTOM -> {
    notificationBuilder
        .setStyle(NotificationCompat.DecoratedCustomViewStyle())
        .setCustomContentView(
            RemoteViews(
                packageName,
                R.layout.view_custom_notification
            ).apply {
                setTextViewText(R.id.title, title)
                setTextViewText(R.id.message, content)
            }
        )
}

 

알림의 배경 색상은 기기나 버전에 따라 달라질 수 있기 때문에, 커스텀 레이아웃의 텍스트는 TextAppearance_Compat_Notification을 제목은 TextAppearance_Compat_Notification_Title 스타일을 항상 적용해야한다.

이를 적용해야 검은색 배경에 검은색 텍스트가 들어가거나 흰색 배경에 흰색 텍스트가 들어가는 것을 방지 할 수 있다.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center">

    <TextView
        android:id="@+id/title"
        style="@style/TextAppearance.Compat.Notification.Title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="25sp"
        tools:text="Title" />

    <TextView
        android:id="@+id/message"
        style="@style/TextAppearance.Compat.Notification"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        tools:text="Message"/>

</LinearLayout>

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

 

맞춤 알림 레이아웃 만들기  |  Android 개발자  |  Android Developers

맞춤 알림 레이아웃 만들기 여러 Android 버전에서 알림이 가장 잘 보이도록 하려면 항상 표준 알림 템플릿을 사용하여 알림을 만들어야 합니다. 하지만 시스템 템플릿이 요구를 충족하지 않을 경

developer.android.com

 

 

  • 확장 가능한 알림 Expandable Notification

기본 알림의 텍스트는 한 줄에 맞춰서 잘린다. 알림을 더 길게 표시하기 위해서는 확장 가능한 알림을 사용할 수 있다.

Expandable Notification

큰 이미지를 추가하고 싶다면 알림 빌더의 setStyle()에 NotificationCompat.BigPictureStyle()을 적용하고, 큰 텍스트 블록을 추가하고 싶다면 NotificationCompat.BigTextStyle을 적용하면 된다.

이 밖에도 메세지에 관한 알림이라면 답장하는 버튼을 추가하거나 미디어 컨트롤 기능도 추가할 수 있다.

 

푸쉬 알림 앱 수신기에서 Custom Notification은 큰 텍스트 블록을 적용하였다.

val notificationBuilder = NotificationCompat.Builder(this, CHANNEL_ID)
    .setSmallIcon(R.drawable.ic_baseline_notifications_24)
    .setContentTitle(title)
    .setContentText(content)
    .setPriority(NotificationCompat.PRIORITY_DEFAULT)
    .setContentIntent(pendingIntent)
    .setAutoCancel(true)
    
NotificationType.EXPANDABLE -> {
    notificationBuilder.setStyle(
        NotificationCompat.BigTextStyle()
            .bigText(
                "\uD83D\uDE00 \uD83D\uDE03 \uD83D\uDE04 \uD83D\uDE01 " +
                        "\uD83D\uDE06 \uD83D\uDE05 \uD83D\uDE02 \uD83E\uDD23 " +
                        "\uD83E\uDD72 ☺️ \uD83D\uDE0A \uD83D\uDE07 " +
                        "\uD83D\uDE42 \uD83D\uDE43 \uD83D\uDE09 \uD83D\uDE0C " +
                        "\uD83D\uDE0D \uD83E\uDD70 \uD83D\uDE18 \uD83D\uDE17 " +
                        "\uD83D\uDE19 \uD83D\uDE1A \uD83D\uDE0B \uD83D\uDE1B " +
                        "\uD83D\uDE1D \uD83D\uDE1C \uD83E\uDD2A \uD83E\uDD28 " +
                        "\uD83E\uDDD0 \uD83E\uDD13 \uD83D\uDE0E \uD83D\uDC7A " +
                        "\uD83E\uDD21 \uD83D\uDCA9 \uD83D\uDC7B \uD83D\uDC80 ☠️" +
                        "☠️ \uD83D\uDC7D \uD83D\uDC7E \uD83E\uDD16 \uD83C\uDF83 " +
                        "\uD83D\uDE3A \uD83D\uDE38 \uD83D\uDE39 \uD83D\uDE3B " +
                        "\uD83D\uDE3C \uD83D\uDE3D \uD83D\uDE40 \uD83D\uDE3F " +
                        "\uD83D\uDE3E"
            )
    )

}

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

 

확장형 알림 만들기  |  Android 개발자  |  Android Developers

확장형 알림 만들기 기본 알림에는 일반적으로 제목, 텍스트 행, 사용자가 응답으로 실행할 수 있는 하나 이상의 작업이 포함됩니다. 훨씬 더 많은 정보를 제공하기 위해 이 페이지에 설명된 대

developer.android.com

 

 

  • NotificationChannel

Android 8.0(API 수준 26)부터는 모든 알림을 채널에 할당해야 한다.

알림 채널을 지정하지 않고 알림을 게시하면 시스템에서 오류가 발생한다.

채널마다 채널의 알림에 적용되는 시각적/음향적 동작을 설정할 수 있다.

사용자는 이러한 설정을 변경하고 앱에서 차단하거나 표시해야하는 알림 채널을 결정할 수 있다.

 

이렇게 사용자는 앱별로 알림 채널을 설정할 수 있다. (사용자 인터페이스에서는 알림 채널을 '카테고리'라고 부른다.)

 

  • 알림 채널 만들기

고유한 채널 ID, 사용자가 볼 수 있는 이름, 중요도를 지정해서 NotificationChannel 객체를 구성한다.

그리고 선택적으로 description을 지정해서 시스템 설정에서 사용자에게 표시되는 설명을 지정할 수 있다.

생성한 알림 채널을 createNotificationChannel()에 전달해서 등록한다.

private fun createNotificationChannel() {
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val channel = NotificationChannel(
            CHANNEL_ID,
            CHANNEL_NAME,
            NotificationManager.IMPORTANCE_DEFAULT
        )
        channel.description = CHANNEL_DESCRIPTION

        (getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager)
            .createNotificationChannel(channel)
    }
}

 

  • 채널의 중요도

채널 중요도는 채널에 게시된 모든 알림의 중단 수준에 영향을 미친다.

IMPORTANCE_NONE(0)에서 IMPORTANCE_HIGH(4)까지 5가지 중요도 수준이 있다.

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

 

알림 채널 만들기 및 관리  |  Android 개발자  |  Android Developers

알림 채널 만들기 및 관리 Android 8.0(API 수준 26)부터는 모든 알림을 채널에 할당해야 합니다. 채널마다 채널의 모든 알림에 적용되는 시각적/음향적 동작을 설정할 수 있습니다. 그런 다음 사용자

developer.android.com

 

 

  • PendingIntent

PendingIntent는 Intent를 가지고 있는 클래스로, 다른 애플리케이션이나 프로세스에 권한을 줘서 PendingIntent의 Intent를 마치 자기 자신의 앱에서 실행하는 것처럼 사용할 수 있도록 합니다.

앱에서 다른 앱에게 작업을 요청하는 Intent를 사전에 생성하고 특정 시점에 자신이 아닌 다른 앱이 PendingIntent를 사용해서 작업을 수행하게 하는 특징이 있다.

 

알림에 관한 이벤트는 안드로이드 시스템 서비스인 NotificationManager가 관리하고 알려준다.

즉, 알림을 사용자가 클릭했을 때 이후 수행되어야 하는 작업을 담은 Intent는 NotificationManager가 실행해야 한다는 것이다.

Intent를 생성한 앱의 프로세스에서 수행되는 것이 아닌 다른 프로세스에서 Intent를 수행해야하므로 PendingIntent를 사용해야 하는 것이다.

 

  • requstCode

PendingIntent는 기본적으로 아직 회수되지 않은 알림들이 존재할 때(클릭되지 않은 알림), PendingIntent 안에 들어있는 데이터가 같다면 동일한 PendingIntent로 처리된다.

즉, 여러 알림이 도착해서 여러 PendingIntent를 생성하였더라도 안에 있는 데이터가 같다면 사실상 동일한 PendingIntent인 것이다.

따라서, Custom, Expandable, Normal 타입의 여러 알림을 발생시키더라도 모든 알림은 마지막으로 도착한 알림에 의해 생성된 PendingIntent로 간주되게 된다.

이를 분류하고 싶다면 PendingIntent를 가져올 때 구분하기 위한 고유 코드인 request code를 타입별로 다르게 설정하면 된다.

 

PendingIntent를 회수해서 새로운 Activity를 시작시키려면 getActivity()를 사용한다.(startActivity(intent)와 유사하다.)

public static PendingIntent getActivity (Context context, 
                int requestCode, 
                Intent intent, 
                int flags)

 

val pendingIntent = PendingIntent.getActivity(this, type.id, intent, FLAG_UPDATE_CURRENT)

val notificationBuilder = NotificationCompat.Builder(this, CHANNEL_ID)
    .setSmallIcon(R.drawable.ic_baseline_notifications_24)
    .setContentTitle(title)
    .setContentText(content)
    .setPriority(NotificationCompat.PRIORITY_DEFAULT)
    .setContentIntent(pendingIntent)
    .setAutoCancel(true)

 

  • FLAG

PendingIndent를 생성할 때 설정할 수 있는 Flag 옵션에는 다음이 있다.

  1. FLAG_CANCEL_CURRENT - 이전에 존재하는 PendingIntent를 취소하고 새로 생성한다.
  2. FLAG_IMMUTABLE - 생성된 PendingIntent를 수정 불가하게 한다.
  3. FLAG_MUTABLE - 생성된 PendingIntent를 수정 가능하게 한다.
  4. FLAG_NO_CREATE - 이전에 생성한 PendingIntent가 있다면 재사용하고 없다면 null을 반환한다.
  5. FLAG_ONE_SHOT - 생성된 PendingIntent를 단 한번만 사용할 수 있다.
  6. FLAG_UPDATE_CURRENT - 기존에 PendingIntent가 존재하면 해당 intent의 Extra data 값을 새 값으로 갱신한다.

 

 

 

728x90
반응형

'Android > Side Projects' 카테고리의 다른 글

오늘의 명언 앱 개발하기  (1) 2022.02.07
오늘의 명언 앱 개발하기  (0) 2022.02.06
푸쉬 알림 수신기 앱 개발하기  (0) 2022.02.04
Simple Web Browser 앱 개발하기  (0) 2022.02.03
녹음기 앱 개발하기  (0) 2022.02.02