#1 이전 글
위 게시글의 완성된 앱을 일부 수정해서, 알림 메시지 클릭 시의 동작을 구현해본다.
#2 PendingIntent
Intent는 안드로이드에서 컴포넌트(Activity, Service, BroadcastReceiver, ContentProvider) 간 통신을 위해 사용되는 메시지 객체다. PendingIntent는 나중에 실행될 Intent를 포장(Wrapping)하는 객체다. 그리고 상태바에 올라갈 알림(Notifications) 메시지에 PendingIntent를 달아줄 수 있는데, 그렇게 함으로써 해당 메시지를 클릭할 때의 동작을 구현해줄 수 있다. PendingIntent가 없다면, 알림 메시지를 클릭해도 아무런 반응이 없다.
#3 코드 수정 - Tab behavior
#3-1 개요
상태바의 알림 패널을 클릭(Tab)하면 반응(특정 액티비티로 이동)하게 만들어본다.
#3-2 MainActivity.kt 수정
...
class MainActivity : AppCompatActivity() {
...
private val channelId = "com.example.pendingintent.channel1"
private val myRequestCode1 = 12345
override fun onCreate(savedInstanceState: Bundle?) {
...
}
private fun displayNotification() {
val notificationId = ...
val tabBehavior = getSecondActivityPendingIntent()
val notification = NotificationCompat.Builder(this@MainActivity, channelId).apply {
...
setContentIntent(tabBehavior)
}.build()
notificationManager?.notify(notificationId, notification)
}
private fun getSecondActivityPendingIntent(): PendingIntent {
val intent = Intent(this, SecondActivity::class.java)
return PendingIntent.getActivity(
this, myRequestCode1, intent, PendingIntent.FLAG_IMMUTABLE
)
}
...
}
위와 같이 코드를 수정한다. PendingIntent.getActivity()의 첫번째 인자는 Context, 두번째 인자는 서로 다른 PendingIntent를 명시적으로 구분하기 위한 Int형 Id값 (나는 아무 숫자인 12345를 넣었다), 세번째 인자는 Intent, 네번째 인자는 PendingIntent의 속성을 정의하는 Int형 상수다. FLAG_IMMUTABLE은 마치 val형 변수의 불변적(Immutable) 성격과 비슷한 맥락으로, 위 코드 속 PendingIntent에 새로운 Intent를 가지게 만드는 등의 변경 사항을 적용할 수 없게 만드는 플래그다.
#3-3 activity_second.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">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="SecondActivity"
android:textSize="40dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
간단한 View.
#3-4 SecondActivity.kt 생성
// package com.anushka.notificationdemo
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
class SecondActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_second)
}
}
비어있는 Activity.
#3-5 AndroidMenifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
...
<application
...>
<activity
android:name=".SecondActivity"
android:exported="false" />
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
AndroidMenifest.xml에 SecondActivity를 등록한다.
#3-6 작동 확인
만약 버튼을 눌러도 알림이 뜨지 않는다면, 설치된 앱의 알림 권한이 차단되지는 않았는지 확인해보자. 기본값 설정이 차단인 경우가 있다.
#4 코드 수정 - Action Button
#4-1 개요
상태바의 알림 패널에 여러 개의 Action Button을 추가한다. 내부적인 코드는 #3과 거의 같다. #3과의 차이는 알림 패널에 클릭 가능한 버튼이 존재하며, 각 버튼에 서로 다른 PendingIntent를 넣어 줄 수 있다는 점이다.
#4-2 MainActivity.kt 수정
...
class MainActivity : AppCompatActivity() {
...
private val myRequestCode2 = 12346
private val myRequestCode3 = 12347
override fun onCreate(savedInstanceState: Bundle?) {
...
}
private fun displayNotification() {
val notificationId = ...
val tabBehavior = getSecondActivityPendingIntent()
val actionButton1 = getThirdActivityAction()
val actionButton2 = getFourthActivityAction()
val notification = NotificationCompat.Builder(this@MainActivity, channelId).apply {
...
setContentIntent(tabBehavior)
addAction(actionButton1)
addAction(actionButton2)
}.build()
notificationManager?.notify(notificationId, notification)
}
private fun getSecondActivityPendingIntent(): PendingIntent {
...
}
private fun getThirdActivityAction(): NotificationCompat.Action {
val intent = Intent(this, ThirdActivity::class.java)
val pendingIntent: PendingIntent = PendingIntent.getActivity(
this, myRequestCode2, intent, PendingIntent.FLAG_IMMUTABLE
)
return NotificationCompat.Action.Builder(0, "Go Third", pendingIntent).build()
}
private fun getFourthActivityAction(): NotificationCompat.Action {
val intent = Intent(this, FourthActivity::class.java)
val pendingIntent: PendingIntent = PendingIntent.getActivity(
this, myRequestCode3, intent, PendingIntent.FLAG_IMMUTABLE
)
return NotificationCompat.Action.Builder(0, "Go Fourth", pendingIntent).build()
}
...
}
Action 버튼은 NotificationCompat.Action의 빌더 클래스인 NotificationCompat.Action.Builder를 통해 만든다. 해당 클래스 생성자의 첫번째 인자는 아이콘(IconCompat), 두번째 인자는 Action 버튼의 제목, 세번째 인자는 PendingIntent다.
#4-3 ThirdActivity와 FourthActivity 관련 코드
코드 생략
#3-3 ~ #3-5와 같은 방식으로, ThirdActivity 및 FourthActivity 그리고 각각의 View를 만든다. AndroidManifest에 만든 Activity를 등록하는 것 또한 잊지 말자.
#4-4 작동 확인
#4-5 필요한 개선점
Action Button을 클릭해도, Notification이 사라지지 않는다. Action Button이 아니라 Notification 자체를 Tab했을 때 Notification이 잘만 사라지던 것과는 대조적이다. 이어지는 게시글(#7 참조)에서 해당 동작을 구현해본다.
#5 요약
PendingIntent는 어떤 것에 매달기(Pend) 위한 Intent다.
#6 완성된 앱
#7 이어지는 글
'깨알 개념 > Android' 카테고리의 다른 글
[Android] WorkManager - 개요 (0) | 2024.06.14 |
---|---|
[Android] Notifications - Action 버튼 클릭 시 알림 Cancel (0) | 2024.06.14 |
[Android] Notifications - 기초 (0) | 2024.06.12 |
[Android] Retrofit - Post (0) | 2024.06.11 |
[Android] Retrofit - Logging, Timeout 관리 (Interceptor) (0) | 2024.06.11 |