Remove PlayerNotificationManager left overs

This commit is contained in:
Bnyro 2023-05-22 16:32:24 +02:00
parent b52583855e
commit 33de6ca827

View File

@ -7,8 +7,6 @@ import android.app.PendingIntent.FLAG_UPDATE_CURRENT
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.drawable.Icon
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.support.v4.media.session.MediaSessionCompat import android.support.v4.media.session.MediaSessionCompat
@ -17,10 +15,8 @@ import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat import androidx.core.app.NotificationManagerCompat
import androidx.core.app.PendingIntentCompat import androidx.core.app.PendingIntentCompat
import androidx.core.content.getSystemService import androidx.core.content.getSystemService
import androidx.core.graphics.drawable.IconCompat
import androidx.core.graphics.drawable.toBitmap import androidx.core.graphics.drawable.toBitmap
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.media.app.NotificationCompat.MediaStyle
import androidx.media3.common.Player import androidx.media3.common.Player
import androidx.media3.exoplayer.ExoPlayer import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.session.CommandButton import androidx.media3.session.CommandButton
@ -39,6 +35,10 @@ import com.github.libretube.helpers.PlayerHelper
import com.github.libretube.obj.PlayerNotificationData import com.github.libretube.obj.PlayerNotificationData
import com.github.libretube.ui.activities.MainActivity import com.github.libretube.ui.activities.MainActivity
import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListenableFuture
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class) @androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class)
class NowPlayingNotification( class NowPlayingNotification(
@ -48,7 +48,6 @@ class NowPlayingNotification(
) { ) {
private var videoId: String? = null private var videoId: String? = null
private var notificationData: PlayerNotificationData? = null private var notificationData: PlayerNotificationData? = null
private var bitmap: Bitmap? = null
/** /**
* The [MediaSessionCompat] for the [notificationData]. * The [MediaSessionCompat] for the [notificationData].
@ -56,72 +55,47 @@ class NowPlayingNotification(
private lateinit var mediaSession: MediaSession private lateinit var mediaSession: MediaSession
/** /**
* The [PlayerNotificationManager] to load the [mediaSession] content on it. * The [NotificationCompat.Builder] to load the [mediaSession] content on it.
*/ */
private var playerNotification: PlayerNotificationManager? = null private var notificationBuilder: NotificationCompat.Builder? = null
/** /**
* The [descriptionAdapter] is used to show title, uploaderName and thumbnail of the video in the notification * The [Bitmap] which represents the background / thumbnail of the notification
* Basic example [here](https://github.com/AnthonyMarkD/AudioPlayerSampleTest)
*/ */
private val descriptionAdapter = object : PlayerNotificationManager.MediaDescriptionAdapter { private var notificationBitmap: Bitmap? = null
/**
* sets the title of the notification
*/
override fun getCurrentContentTitle(player: Player): CharSequence {
return notificationData?.title.orEmpty()
}
/** private val nManager = NotificationManagerCompat.from(context)
* overrides the action when clicking the notification
*/
override fun createCurrentContentIntent(player: Player): PendingIntent {
// starts a new MainActivity Intent when the player notification is clicked
// it doesn't start a completely new MainActivity because the MainActivity's launchMode
// is set to "singleTop" in the AndroidManifest (important!!!)
// that's the only way to launch back into the previous activity (e.g. the player view
val intent = Intent(context, MainActivity::class.java).apply {
if (isBackgroundPlayerNotification) {
putExtra(IntentData.openAudioPlayer, true)
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
}
}
return PendingIntentCompat.getActivity(context, 0, intent, FLAG_UPDATE_CURRENT, false)
}
/** private fun loadCurrentLargeIcon() {
* the description of the notification (below the title) // On Android 13 and up, the metadata is responsible for the thumbnail
*/ if (DataSaverMode.isEnabled(context) ||
override fun getCurrentContentText(player: Player): CharSequence? { Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) return
return notificationData?.uploaderName if (notificationBitmap == null) enqueueThumbnailRequest {
} createOrUpdateNotification()
/**
* return the icon/thumbnail of the video
*/
override fun getCurrentLargeIcon(
player: Player,
callback: PlayerNotificationManager.BitmapCallback,
): Bitmap? {
// On Android 13 and up, the metadata is responsible for the thumbnail
if (DataSaverMode.isEnabled(context) ||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) return null
if (bitmap == null) enqueueThumbnailRequest(callback)
return bitmap
}
override fun getCurrentSubText(player: Player): CharSequence? {
return notificationData?.uploaderName
} }
} }
private fun enqueueThumbnailRequest(callback: PlayerNotificationManager.BitmapCallback) { private fun createCurrentContentIntent(): PendingIntent {
// starts a new MainActivity Intent when the player notification is clicked
// it doesn't start a completely new MainActivity because the MainActivity's launchMode
// is set to "singleTop" in the AndroidManifest (important!!!)
// that's the only way to launch back into the previous activity (e.g. the player view
val intent = Intent(context, MainActivity::class.java).apply {
if (isBackgroundPlayerNotification) {
putExtra(IntentData.openAudioPlayer, true)
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
}
}
return PendingIntentCompat.getActivity(context, 0, intent, FLAG_UPDATE_CURRENT, false)
}
private fun enqueueThumbnailRequest(callback: (Bitmap) -> Unit) {
// If playing a downloaded file, show the downloaded thumbnail instead of loading an // If playing a downloaded file, show the downloaded thumbnail instead of loading an
// online image // online image
notificationData?.thumbnailPath?.let { path -> notificationData?.thumbnailPath?.let { path ->
ImageHelper.getDownloadedImage(context, path)?.let { ImageHelper.getDownloadedImage(context, path)?.let {
bitmap = ImageHelper.getSquareBitmap(it) notificationBitmap = ImageHelper.getSquareBitmap(it)
callback.onBitmap(bitmap!!) callback.invoke(notificationBitmap!!)
} }
return return
} }
@ -129,8 +103,8 @@ class NowPlayingNotification(
val request = ImageRequest.Builder(context) val request = ImageRequest.Builder(context)
.data(notificationData?.thumbnailUrl) .data(notificationData?.thumbnailUrl)
.target { .target {
bitmap = ImageHelper.getSquareBitmap(it.toBitmap()) notificationBitmap = ImageHelper.getSquareBitmap(it.toBitmap())
callback.onBitmap(bitmap!!) callback.invoke(notificationBitmap!!)
} }
.build() .build()
@ -138,27 +112,12 @@ class NowPlayingNotification(
ImageHelper.imageLoader.enqueue(request) ImageHelper.imageLoader.enqueue(request)
} }
private val customActionReceiver = object : PlayerNotificationManager.CustomActionReceiver { private val customActions = listOf(
override fun createCustomActions( createNotificationAction(R.drawable.ic_prev_outlined, PREV, 1),
context: Context, createNotificationAction(R.drawable.ic_next_outlined, NEXT, 1),
instanceId: Int, createNotificationAction(R.drawable.ic_rewind_md, REWIND, 1),
): MutableMap<String, NotificationCompat.Action> { createNotificationAction(R.drawable.ic_forward_md, FORWARD, 1),
return mutableMapOf( )
PREV to createNotificationAction(R.drawable.ic_prev_outlined, PREV, instanceId),
NEXT to createNotificationAction(R.drawable.ic_next_outlined, NEXT, instanceId),
REWIND to createNotificationAction(R.drawable.ic_rewind_md, REWIND, instanceId),
FORWARD to createNotificationAction(R.drawable.ic_forward_md, 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( private fun createNotificationAction(
drawableRes: Int, drawableRes: Int,
@ -279,7 +238,7 @@ class NowPlayingNotification(
} }
/** /**
* Updates or creates the [playerNotification] * Updates or creates the [notificationBuilder]
*/ */
fun updatePlayerNotification( fun updatePlayerNotification(
videoId: String, videoId: String,
@ -288,61 +247,48 @@ class NowPlayingNotification(
this.videoId = videoId this.videoId = videoId
this.notificationData = data this.notificationData = data
// reset the thumbnail bitmap in order to become reloaded for the new video // reset the thumbnail bitmap in order to become reloaded for the new video
this.bitmap = null this.notificationBitmap = null
if (playerNotification == null) { loadCurrentLargeIcon()
if (notificationBuilder == null) {
createMediaSession() createMediaSession()
createNotification() createNotificationBuilder()
} }
createOrUpdateNotification()
} }
/** /**
* Initializes the [playerNotification] attached to the [player] and shows it. * Initializes the [notificationBuilder] attached to the [player] and shows it.
*/ */
@SuppressLint("MissingPermission") private fun createNotificationBuilder() {
private fun createNotification() { notificationBuilder = NotificationCompat.Builder(context, BACKGROUND_CHANNEL_ID)
/** .setSmallIcon(R.drawable.ic_launcher_lockscreen)
playerNotification = PlayerNotificationManager .setContentIntent(createCurrentContentIntent())
.Builder(context, PLAYER_NOTIFICATION_ID, BACKGROUND_CHANNEL_ID) .setStyle(MediaStyleNotificationHelper.MediaStyle(mediaSession))
// set the description of the notification .setLargeIcon(notificationBitmap)
.setMediaDescriptionAdapter(descriptionAdapter)
// register the receiver for custom actions, doesn't seem to change anything
.setCustomActionReceiver(customActionReceiver)
.build().apply {
setPlayer(player)
setColorized(true)
setMediaSessionToken(mediaSession.sessionCompatToken)
setSmallIcon(R.drawable.ic_launcher_lockscreen)
setUseNextAction(false)
setUsePreviousAction(false)
setUseRewindAction(false)
setUseFastForwardAction(false)
setUseStopAction(true)
}
**/
val notification = NotificationCompat.Builder(context, BACKGROUND_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_launcher_lockscreen)
.setContentIntent(descriptionAdapter.createCurrentContentIntent(player))
.setStyle(MediaStyle().setMediaSession(mediaSession.sessionCompatToken))
.setContentTitle(player.mediaMetadata.title)
.setContentText(player.mediaMetadata.artist)
.setLargeIcon(BitmapFactory.decodeResource(context.resources, R.mipmap.ic_bird))
.apply { .apply {
customActionReceiver.createCustomActions(context, 0).forEach { customActions.forEach {
addAction(it.value) addAction(it)
} }
} }
}
val nManager = NotificationManagerCompat.from(context) @SuppressLint("MissingPermission")
nManager.notify(PLAYER_NOTIFICATION_ID, notification.build()) private fun createOrUpdateNotification() {
if (notificationBuilder == null) return
val notification = notificationBuilder!!
.setContentText(notificationData?.title)
.setContentText(notificationData?.uploaderName)
.build()
nManager.notify(PLAYER_NOTIFICATION_ID, notification)
} }
/** /**
* Destroy the [NowPlayingNotification] * Destroy the [NowPlayingNotification]
*/ */
fun destroySelfAndPlayer() { fun destroySelfAndPlayer() {
playerNotification?.setPlayer(null)
mediaSession.release() mediaSession.release()
player.stop() player.stop()