mirror of
https://github.com/libre-tube/LibreTube.git
synced 2025-04-28 07:50:31 +05:30
Merge pull request #1580 from Bnyro/master
Improved now playing notification behavior
This commit is contained in:
commit
2cd78cd6fc
@ -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(
|
||||||
|
@ -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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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() {
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user