Kotlin

[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

 

Leave a Reply

error: Content is protected !!