Merge pull request #1580 from Bnyro/master

Improved now playing notification behavior
This commit is contained in:
Bnyro 2022-10-17 17:19:17 +00:00 committed by GitHub
commit 2cd78cd6fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 89 additions and 38 deletions

View File

@ -9,14 +9,20 @@ import android.os.Build
import android.os.Handler import android.os.Handler
import android.os.IBinder import android.os.IBinder
import android.os.Looper import android.os.Looper
import android.util.Log
import android.widget.Toast import android.widget.Toast
import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.ObjectMapper
import com.github.libretube.R import com.github.libretube.R
import com.github.libretube.api.RetrofitInstance import com.github.libretube.api.RetrofitInstance
import com.github.libretube.api.obj.Segments
import com.github.libretube.api.obj.Streams
import com.github.libretube.constants.BACKGROUND_CHANNEL_ID import com.github.libretube.constants.BACKGROUND_CHANNEL_ID
import com.github.libretube.constants.IntentData import com.github.libretube.constants.IntentData
import com.github.libretube.constants.PLAYER_NOTIFICATION_ID import com.github.libretube.constants.PLAYER_NOTIFICATION_ID
import com.github.libretube.constants.PreferenceKeys import com.github.libretube.constants.PreferenceKeys
import com.github.libretube.db.DatabaseHelper
import com.github.libretube.db.DatabaseHolder
import com.github.libretube.extensions.awaitQuery
import com.github.libretube.extensions.toID import com.github.libretube.extensions.toID
import com.github.libretube.util.AutoPlayHelper import com.github.libretube.util.AutoPlayHelper
import com.github.libretube.util.NowPlayingNotification import com.github.libretube.util.NowPlayingNotification
@ -50,7 +56,7 @@ class BackgroundMode : Service() {
/** /**
* The response that gets when called the Api. * The response that gets when called the Api.
*/ */
private var streams: com.github.libretube.api.obj.Streams? = null private var streams: Streams? = null
/** /**
* The [ExoPlayer] player. Followed tutorial [here](https://developer.android.com/codelabs/exoplayer-intro) * The [ExoPlayer] player. Followed tutorial [here](https://developer.android.com/codelabs/exoplayer-intro)
@ -66,7 +72,7 @@ class BackgroundMode : Service() {
/** /**
* SponsorBlock Segment data * SponsorBlock Segment data
*/ */
private var segmentData: com.github.libretube.api.obj.Segments? = null private var segmentData: Segments? = null
/** /**
* [Notification] for the player * [Notification] for the player
@ -127,12 +133,19 @@ class BackgroundMode : Service() {
// play the audio in the background // play the audio in the background
loadAudio(videoId, position) loadAudio(videoId, position)
updateWatchPosition()
} catch (e: Exception) { } catch (e: Exception) {
onDestroy() onDestroy()
} }
return super.onStartCommand(intent, flags, startId) return super.onStartCommand(intent, flags, startId)
} }
private fun updateWatchPosition() {
player?.currentPosition?.let { DatabaseHelper.saveWatchPosition(videoId, it) }
handler.postDelayed(this::updateWatchPosition, 500)
}
/** /**
* Gets the video data and prepares the [player]. * Gets the video data and prepares the [player].
*/ */
@ -165,9 +178,9 @@ class BackgroundMode : Service() {
// create the notification // create the notification
if (!this@BackgroundMode::nowPlayingNotification.isInitialized) { if (!this@BackgroundMode::nowPlayingNotification.isInitialized) {
nowPlayingNotification = NowPlayingNotification(this@BackgroundMode, player!!) nowPlayingNotification = NowPlayingNotification(this@BackgroundMode, player!!, true)
} }
nowPlayingNotification.updatePlayerNotification(streams!!) nowPlayingNotification.updatePlayerNotification(videoId, streams!!)
player?.apply { player?.apply {
playWhenReady = playWhenReadyPlayer playWhenReady = playWhenReadyPlayer
@ -175,7 +188,23 @@ class BackgroundMode : Service() {
} }
// seek to the previous position if available // seek to the previous position if available
if (seekToPosition != 0L) player?.seekTo(seekToPosition) if (seekToPosition != 0L) {
player?.seekTo(seekToPosition)
} else if (PlayerHelper.watchPositionsEnabled) {
try {
val watchPosition = awaitQuery {
DatabaseHolder.Database.watchPositionDao().findById(videoId)
}
Log.e("position", watchPosition.toString())
streams?.duration?.let {
if (watchPosition != null && watchPosition.position < it * 1000 * 0.9) {
player?.seekTo(watchPosition.position)
}
}
} catch (e: Exception) {
e.printStackTrace()
}
}
// set the playback speed // set the playback speed
val playbackSpeed = PreferenceHelper.getString( val playbackSpeed = PreferenceHelper.getString(

View File

@ -309,30 +309,31 @@ class MainActivity : BaseActivity() {
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
// check whether an URI got submitted over the intent data and load it // check whether an URI got submitted over the intent data and load it
when { loadIntentData()
intent?.getStringExtra(IntentData.channelId) != null -> navController.navigate( }
private fun loadIntentData() {
intent?.getStringExtra(IntentData.channelId)?.let {
navController.navigate(
R.id.channelFragment, R.id.channelFragment,
bundleOf( bundleOf(IntentData.channelName to it)
IntentData.channelName to intent?.getStringExtra(IntentData.channelId)!!
)
) )
intent?.getStringExtra(IntentData.channelName) != null -> navController.navigate( }
intent?.getStringExtra(IntentData.channelName)?.let {
navController.navigate(
R.id.channelFragment, R.id.channelFragment,
bundleOf( bundleOf(IntentData.channelName to it)
IntentData.channelName to intent?.getStringExtra(IntentData.channelName)
)
) )
intent?.getStringExtra(IntentData.playlistId) != null -> navController.navigate( }
intent?.getStringExtra(IntentData.playlistId)?.let {
navController.navigate(
R.id.playlistFragment, R.id.playlistFragment,
bundleOf( bundleOf(IntentData.playlistId to it)
IntentData.playlistId to intent?.getStringExtra(IntentData.playlistId)!!
)
)
intent?.getStringExtra(IntentData.videoId) != null -> loadVideo(
videoId = intent?.getStringExtra(IntentData.videoId)!!,
timeStamp = intent?.getLongExtra(IntentData.timeStamp, 0L)
) )
} }
intent?.getStringExtra(IntentData.videoId)?.let {
loadVideo(it, intent?.getLongExtra(IntentData.timeStamp, 0L))
}
} }
private fun loadVideo(videoId: String, timeStamp: Long?) { private fun loadVideo(videoId: String, timeStamp: Long?) {
@ -489,4 +490,10 @@ class MainActivity : BaseActivity() {
(fragment as? PlayerFragment)?.onUserLeaveHint() (fragment as? PlayerFragment)?.onUserLeaveHint()
} }
} }
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
this.intent = intent
loadIntentData()
}
} }

View File

@ -1282,9 +1282,9 @@ class PlayerFragment : BaseFragment() {
*/ */
private fun initializePlayerNotification() { private fun initializePlayerNotification() {
if (!this::nowPlayingNotification.isInitialized) { if (!this::nowPlayingNotification.isInitialized) {
nowPlayingNotification = NowPlayingNotification(requireContext(), exoPlayer) nowPlayingNotification = NowPlayingNotification(requireContext(), exoPlayer, false)
} }
nowPlayingNotification.updatePlayerNotification(streams) nowPlayingNotification.updatePlayerNotification(videoId!!, streams)
} }
private fun isSubscribed() { private fun isSubscribed() {

View File

@ -1,5 +1,6 @@
package com.github.libretube.util package com.github.libretube.util
import android.annotation.SuppressLint
import android.app.NotificationManager import android.app.NotificationManager
import android.app.PendingIntent import android.app.PendingIntent
import android.content.Context import android.content.Context
@ -9,7 +10,9 @@ import android.graphics.drawable.BitmapDrawable
import android.os.Build import android.os.Build
import android.support.v4.media.session.MediaSessionCompat import android.support.v4.media.session.MediaSessionCompat
import coil.request.ImageRequest import coil.request.ImageRequest
import com.github.libretube.api.obj.Streams
import com.github.libretube.constants.BACKGROUND_CHANNEL_ID import com.github.libretube.constants.BACKGROUND_CHANNEL_ID
import com.github.libretube.constants.IntentData
import com.github.libretube.constants.PLAYER_NOTIFICATION_ID import com.github.libretube.constants.PLAYER_NOTIFICATION_ID
import com.github.libretube.ui.activities.MainActivity import com.github.libretube.ui.activities.MainActivity
import com.google.android.exoplayer2.ExoPlayer import com.google.android.exoplayer2.ExoPlayer
@ -19,9 +22,11 @@ import com.google.android.exoplayer2.ui.PlayerNotificationManager
class NowPlayingNotification( class NowPlayingNotification(
private val context: Context, private val context: Context,
private val player: ExoPlayer private val player: ExoPlayer,
private val isBackgroundPlayerNotification: Boolean
) { ) {
private var streams: com.github.libretube.api.obj.Streams? = null private var videoId: String? = null
private var streams: Streams? = null
/** /**
* The [MediaSessionCompat] for the [streams]. * The [MediaSessionCompat] for the [streams].
@ -48,30 +53,35 @@ class NowPlayingNotification(
* sets the title of the notification * sets the title of the notification
*/ */
override fun getCurrentContentTitle(player: Player): CharSequence { override fun getCurrentContentTitle(player: Player): CharSequence {
// return controller.metadata.description.title.toString()
return streams?.title!! return streams?.title!!
} }
/** /**
* overrides the action when clicking the notification * overrides the action when clicking the notification
*/ */
@SuppressLint("UnspecifiedImmutableFlag")
override fun createCurrentContentIntent(player: Player): PendingIntent? { override fun createCurrentContentIntent(player: Player): PendingIntent? {
// return controller.sessionActivity // starts a new MainActivity Intent when the player notification is clicked
/** // it doesn't start a completely new MainActivity because the MainActivity's launchMode
* starts a new MainActivity Intent when the player notification is clicked // is set to "singleTop" in the AndroidManifest (important!!!)
* it doesn't start a completely new MainActivity because the MainActivity's launchMode // that's the only way to launch back into the previous activity (e.g. the player view
* is set to "singleTop" in the AndroidManifest (important!!!) val intent = Intent(context, MainActivity::class.java).apply {
* that's the only way to launch back into the previous activity (e.g. the player view if (isBackgroundPlayerNotification) {
*/ putExtra(IntentData.videoId, videoId)
val intent = Intent(context, MainActivity::class.java) addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE) }
}
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT)
} else {
PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
}
} }
/** /**
* the description of the notification (below the title) * the description of the notification (below the title)
*/ */
override fun getCurrentContentText(player: Player): CharSequence? { override fun getCurrentContentText(player: Player): CharSequence? {
// return controller.metadata.description.subtitle.toString()
return streams?.uploader return streams?.uploader
} }
@ -121,9 +131,12 @@ class NowPlayingNotification(
* Updates or creates the [playerNotification] * Updates or creates the [playerNotification]
*/ */
fun updatePlayerNotification( fun updatePlayerNotification(
streams: com.github.libretube.api.obj.Streams videoId: String,
streams: Streams
) { ) {
this.videoId = videoId
this.streams = streams this.streams = streams
if (playerNotification == null) { if (playerNotification == null) {
createMediaSession() createMediaSession()
createNotification() createNotification()
@ -161,10 +174,12 @@ class NowPlayingNotification(
mediaSession.release() mediaSession.release()
mediaSessionConnector.setPlayer(null) mediaSessionConnector.setPlayer(null)
playerNotification?.setPlayer(null) playerNotification?.setPlayer(null)
val notificationManager = context.getSystemService( val notificationManager = context.getSystemService(
Context.NOTIFICATION_SERVICE Context.NOTIFICATION_SERVICE
) as NotificationManager ) as NotificationManager
notificationManager.cancel(PLAYER_NOTIFICATION_ID) notificationManager.cancel(PLAYER_NOTIFICATION_ID)
player.stop() player.stop()
player.release() player.release()
} }