[android : kotlin] 코틀린 Notification addAction 추가하는 방법(.apply) : Notification.Action.Builder
코틀린에서 빌더를 먼저 생성 후 addAction을 하려고 하면 addAction메서드를 사용할 수 없다.
아래 코드 스니펫 처럼 NotificationCompat.Builder를 먼저 생성후 필요에 따라 action를 분기 해야할 필요가 있을 경우가 있다. 자바에서 처럼 builder.addAction() 메서드를 사용하려고 보니, 사용할 수 없다. 다른 방법으로 구현을 해야한다.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val builder = NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle(description.title)
.setContentText(description.subtitle)
.setSubText(description.description)
// Show controls on lock screen even when user hides sensitive content.
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setAutoCancel(false)
//.setWhen(System.currentTimeMillis())
.setContentIntent(controller.sessionActivity)
.setSmallIcon(R.mipmap.ic_launcher_round)
.setLargeIcon(description.iconBitmap)
.setDeleteIntent(
MediaButtonReceiver.buildMediaButtonPendingIntent(
this,
PlaybackStateCompat.ACTION_STOP
)
)
//.setWhen(System.currentTimeMillis())
.setStyle(
androidx.media.app.NotificationCompat.MediaStyle()
.setMediaSession(sessionToken)
.setShowActionsInCompactView(
0,
1,
2
)
.setShowCancelButton(true)
.setCancelButtonIntent(
MediaButtonReceiver.buildMediaButtonPendingIntent(
this, PlaybackStateCompat.ACTION_STOP
)
)
)
//.setColor(ContextCompat.getColor(this, R.color.colorAccent))
.setShowWhen(false)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setOnlyAlertOnce(true)
.setChannelId(CHANNEL_ID)
.build()
}
아래 코드스니펫을 보자. Notificaiotn.action를 사용해서 PendingIntent를 설정해야한다.
val previous =
Notification.Action.Builder(
R.drawable.baseline_skip_previous_24,
getString(R.string.previous),
MediaButtonReceiver.buildMediaButtonPendingIntent(
this,
PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS
)
).build()
val next =
Notification.Action.Builder(
R.drawable.baseline_skip_next_24,
getString(R.string.next),
MediaButtonReceiver.buildMediaButtonPendingIntent(
this,
PlaybackStateCompat.ACTION_SKIP_TO_NEXT
)
).build()
lateinit var playpause: Notification.Action
if(playbackState == PlaybackStateCompat.STATE_PLAYING) {
playpause =
Notification.Action.Builder(
R.drawable.baseline_pause_circle_outline_24,
getString(R.string.pause),
MediaButtonReceiver.buildMediaButtonPendingIntent(
this,
PlaybackStateCompat.ACTION_PLAY_PAUSE
)
).build()
} else {
playpause =
Notification.Action.Builder(
R.drawable.baseline_play_circle_outline_24,
getString(R.string.play),
MediaButtonReceiver.buildMediaButtonPendingIntent(
this,
PlaybackStateCompat.ACTION_PLAY_PAUSE
)
).build()
}
Notification클래스의 actions는 리턴값으로 Action[] 배열을 갖는다.
/**
* Array of all {@link Action} structures attached to this notification by
* {@link Builder#addAction(int, CharSequence, PendingIntent)}. Mostly useful for instances of
* {@link android.service.notification.NotificationListenerService} that provide an alternative
* interface for invoking actions.
*/
public Action[] actions;
그럼 준비가 완료되었다면 actions 배열을 초기화 후 각각 인덱스 번호를 지정 후 배열에 넣어주자.
//var btnActions: Array<Notification.Action> = emptyArray<Notification.Action>()
var btnActions: Array<Notification.Action?> = arrayOfNulls<Notification.Action>(3)
btnActions[0] = previous
btnActions[1] = playpause
btnActions[2] = next
builder.actions = btnActions
또 다른방법으로 apply 메서드를 사용하여 분기문을 적용할 수 있다.
val builder = NotificationCompat.Builder(this, CHANNEL_ID).apply {
setContentTitle(description.title)
setContentText(description.subtitle)
setSubText(description.description)
setLargeIcon(description.iconBitmap) // 반드시 bitmap호출
// Show controls on lock screen even when user hides sensitive content.
setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
// Enable launching the player by clicking the notification
setContentIntent(controller.sessionActivity)
// Add an app icon and set its accent color
// Be careful about the color
//color = ContextCompat.getColor(context, R.color.primaryDark)
setSmallIcon(R.mipmap.ic_launcher_round)
setShowWhen(false)
priority = NotificationCompat.PRIORITY_HIGH
//setOnlyAlertOnce(true)
//setChannelId(CHANNEL_ID)
setDeleteIntent(
MediaButtonReceiver.buildMediaButtonPendingIntent(
applicationContext,
PlaybackStateCompat.ACTION_STOP
)
)
addAction((
R.drawable.baseline_skip_previous_24,
getString(R.string.previous),
MediaButtonReceiver.buildMediaButtonPendingIntent(
applicationContext,
PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS
)
).build()
// Add a pause button
if(playbackState == PlaybackStateCompat.STATE_PLAYING) {
addAction(
NotificationCompat.Action(
R.drawable.baseline_pause_circle_outline_24,
getString(R.string.pause),
MediaButtonReceiver.buildMediaButtonPendingIntent(
applicationContext,
PlaybackStateCompat.ACTION_PLAY_PAUSE
)
)
)
}else{
addAction(
R.drawable.baseline_play_circle_outline_24,
getString(R.string.play),
MediaButtonReceiver.buildMediaButtonPendingIntent(
applicationContext,
PlaybackStateCompat.ACTION_PLAY_PAUSE
)
).build()
}
addAction(
R.drawable.baseline_skip_next_24,
getString(R.string.next),
MediaButtonReceiver.buildMediaButtonPendingIntent(
applicationContext,
PlaybackStateCompat.ACTION_SKIP_TO_NEXT
)
).build()
// Take advantage of MediaStyle features
setStyle(
androidx.media.app.NotificationCompat.MediaStyle()
.setMediaSession(sessionToken)
.setShowActionsInCompactView(1)
// Add a cancel button
.setShowCancelButton(true)
.setCancelButtonIntent(
MediaButtonReceiver.buildMediaButtonPendingIntent(
applicationContext, PlaybackStateCompat.ACTION_STOP
)
)
)
}
[build.gradle(:app)]
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 29
defaultConfig {
applicationId "edu.kotlin.study"
minSdkVersion 22
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.1'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
[REFERENCE]
stackoverflow.com/questions/35647821/android-notification-addaction-deprecated-in-api-23
[연관 글 더보기]
[프로그래밍/Kotlin] – [android : kotlin] 코틀린 Notification 사용 예제
[프로그래밍/Android] – 잠금화면에 알림내용(NotificationCompat) 노출하기 (to show content in lock screen