Add custom notification actions

This commit is contained in:
Bnyro 2023-01-15 14:26:55 +01:00
parent 12d4ee9e8e
commit 90e87c596e

View File

@ -5,7 +5,6 @@ import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.res.Resources
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.drawable.BitmapDrawable
@ -14,6 +13,10 @@ import android.os.Bundle
import android.support.v4.media.MediaDescriptionCompat
import android.support.v4.media.MediaMetadataCompat
import android.support.v4.media.session.MediaSessionCompat
import android.support.v4.media.session.PlaybackStateCompat
import android.util.Log
import androidx.annotation.DrawableRes
import androidx.core.app.NotificationCompat
import coil.request.ImageRequest
import com.github.libretube.R
import com.github.libretube.api.obj.Streams
@ -27,6 +30,7 @@ import com.google.android.exoplayer2.Player
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector
import com.google.android.exoplayer2.ext.mediasession.TimelineQueueNavigator
import com.google.android.exoplayer2.ui.PlayerNotificationManager
import com.google.android.exoplayer2.ui.PlayerNotificationManager.CustomActionReceiver
class NowPlayingNotification(
private val context: Context,
@ -52,11 +56,10 @@ class NowPlayingNotification(
private var playerNotification: PlayerNotificationManager? = null
/**
* The [DescriptionAdapter] is used to show title, uploaderName and thumbnail of the video in the notification
* The [descriptionAdapter] is used to show title, uploaderName and thumbnail of the video in the notification
* Basic example [here](https://github.com/AnthonyMarkD/AudioPlayerSampleTest)
*/
inner class DescriptionAdapter :
PlayerNotificationManager.MediaDescriptionAdapter {
private val descriptionAdapter = object : PlayerNotificationManager.MediaDescriptionAdapter {
/**
* sets the title of the notification
*/
@ -125,6 +128,51 @@ class NowPlayingNotification(
}
}
private val customActionReceiver = object : CustomActionReceiver {
override fun createCustomActions(
context: Context,
instanceId: Int
): MutableMap<String, NotificationCompat.Action> {
return mutableMapOf(
PREV to createNotificationAction(R.drawable.ic_prev, PREV, instanceId),
NEXT to createNotificationAction(R.drawable.ic_next, NEXT, instanceId),
REWIND to createNotificationAction(R.drawable.ic_rewind, REWIND, instanceId),
FORWARD to createNotificationAction(R.drawable.ic_forward, FORWARD, instanceId)
)
}
override fun getCustomActions(player: Player): MutableList<String> {
return mutableListOf(PREV, NEXT, REWIND, FORWARD)
}
override fun onCustomAction(player: Player, action: String, intent: Intent) {
handlePlayerAction(action)
}
}
private fun createNotificationAction(drawableRes: Int, actionName: String, instanceId: Int): NotificationCompat.Action {
val intent: Intent = Intent(actionName).setPackage(context.packageName)
val pendingIntent = PendingIntent.getBroadcast(
context,
instanceId,
intent,
PendingIntentCompat.cancelCurrentFlags
)
return NotificationCompat.Action.Builder(drawableRes, actionName, pendingIntent).build()
}
private fun createMediaSessionAction(@DrawableRes drawableRes: Int, actionName: String): MediaSessionConnector.CustomActionProvider {
return object : MediaSessionConnector.CustomActionProvider {
override fun getCustomAction(player: Player): PlaybackStateCompat.CustomAction? {
return PlaybackStateCompat.CustomAction.Builder(actionName, actionName, drawableRes).build()
}
override fun onCustomAction(player: Player, action: String, extras: Bundle?) {
handlePlayerAction(action)
}
}
}
/**
* Creates a [MediaSessionCompat] amd a [MediaSessionConnector] for the player
*/
@ -142,22 +190,50 @@ class NowPlayingNotification(
return MediaDescriptionCompat.Builder().apply {
setTitle(streams?.title!!)
setSubtitle(streams?.uploader)
val extras = Bundle()
val appIcon = BitmapFactory.decodeResource(
Resources.getSystem(),
context.resources,
R.drawable.ic_launcher_monochrome
)
extras.putParcelable(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON, appIcon)
extras.putString(MediaMetadataCompat.METADATA_KEY_TITLE, streams?.title!!)
extras.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, streams?.uploader)
val extras = Bundle().apply {
putParcelable(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON, appIcon)
putString(MediaMetadataCompat.METADATA_KEY_TITLE, streams?.title!!)
putString(MediaMetadataCompat.METADATA_KEY_ARTIST, streams?.uploader)
}
setIconBitmap(appIcon)
setExtras(extras)
}.build()
}
})
mediaSessionConnector.setCustomActionProviders(
createMediaSessionAction(R.drawable.ic_prev, PREV),
createMediaSessionAction(R.drawable.ic_next, NEXT),
createMediaSessionAction(R.drawable.ic_rewind, REWIND),
createMediaSessionAction(R.drawable.ic_forward, FORWARD)
)
mediaSessionConnector.setPlayer(player)
}
private fun handlePlayerAction(action: String) {
when (action) {
NEXT -> {
if (PlayingQueue.hasNext()) PlayingQueue.onQueueItemSelected(
PlayingQueue.currentIndex() + 1
)
}
PREV -> {
if (PlayingQueue.hasPrev()) PlayingQueue.onQueueItemSelected(
PlayingQueue.currentIndex() - 1
)
}
REWIND -> {
player.seekTo(player.currentPosition - PlayerHelper.seekIncrement)
}
FORWARD -> {
player.seekTo(player.currentPosition + PlayerHelper.seekIncrement)
}
}
}
/**
* Updates or creates the [playerNotification]
*/
@ -181,20 +257,17 @@ class NowPlayingNotification(
playerNotification = PlayerNotificationManager
.Builder(context, PLAYER_NOTIFICATION_ID, BACKGROUND_CHANNEL_ID)
// set the description of the notification
.setMediaDescriptionAdapter(
DescriptionAdapter()
)
.build()
playerNotification?.apply {
.setMediaDescriptionAdapter(descriptionAdapter)
// register the receiver for custom actions, doesn't seem to change anything
.setCustomActionReceiver(customActionReceiver)
.build().apply {
setPlayer(player)
setUseNextAction(false)
setUsePreviousAction(false)
setUseStopAction(true)
setColorized(true)
setMediaSessionToken(mediaSession.sessionToken)
setSmallIcon(R.drawable.ic_launcher_lockscreen)
setUseFastForwardActionInCompactView(true)
setUseRewindActionInCompactView(true)
setUseNextAction(false)
setUsePreviousAction(false)
setUseStopAction(true)
}
}
@ -215,4 +288,11 @@ class NowPlayingNotification(
) as NotificationManager
notificationManager.cancel(PLAYER_NOTIFICATION_ID)
}
companion object {
private const val PREV = "prev"
private const val NEXT = "next"
private const val REWIND = "rewind"
private const val FORWARD = "forward"
}
}