diff --git a/app/src/main/java/com/github/libretube/constants/IntentData.kt b/app/src/main/java/com/github/libretube/constants/IntentData.kt index cbce36a215..ee3659ee86 100644 --- a/app/src/main/java/com/github/libretube/constants/IntentData.kt +++ b/app/src/main/java/com/github/libretube/constants/IntentData.kt @@ -2,14 +2,12 @@ package com.github.libretube.constants object IntentData { const val downloadData = "downloadData" + const val playerData = "playerData" const val videoId = "videoId" const val channelId = "channelId" const val channelName = "channelName" const val playlistId = "playlistId" const val timeStamp = "timeStamp" - const val position = "position" - const val fileName = "fileName" - const val keepQueue = "keepQueue" const val playlistType = "playlistType" const val downloading = "downloading" const val openAudioPlayer = "openAudioPlayer" diff --git a/app/src/main/java/com/github/libretube/extensions/Bundle.kt b/app/src/main/java/com/github/libretube/extensions/Bundle.kt new file mode 100644 index 0000000000..5ba01aa6eb --- /dev/null +++ b/app/src/main/java/com/github/libretube/extensions/Bundle.kt @@ -0,0 +1,9 @@ +package com.github.libretube.extensions + +import android.os.Bundle +import android.os.Parcelable +import androidx.core.os.BundleCompat + +inline fun Bundle.parcelable(key: String?): T? { + return BundleCompat.getParcelable(this, key, T::class.java) +} diff --git a/app/src/main/java/com/github/libretube/helpers/BackgroundHelper.kt b/app/src/main/java/com/github/libretube/helpers/BackgroundHelper.kt index 9db55b99e0..c551698a9c 100644 --- a/app/src/main/java/com/github/libretube/helpers/BackgroundHelper.kt +++ b/app/src/main/java/com/github/libretube/helpers/BackgroundHelper.kt @@ -7,8 +7,8 @@ import androidx.core.content.ContextCompat import androidx.core.content.getSystemService import androidx.fragment.app.commit import com.github.libretube.constants.IntentData +import com.github.libretube.parcelable.PlayerData import com.github.libretube.services.OnlinePlayerService -import com.github.libretube.ui.activities.MainActivity import com.github.libretube.ui.fragments.PlayerFragment /** @@ -23,10 +23,10 @@ object BackgroundHelper { fun playOnBackground( context: Context, videoId: String, - position: Long? = null, + position: Long = 0, playlistId: String? = null, channelId: String? = null, - keepQueue: Boolean? = null, + keepQueue: Boolean = false, keepVideoPlayerAlive: Boolean = false, ) { // close the previous video player if open @@ -38,12 +38,9 @@ object BackgroundHelper { } // create an intent for the background mode service + val playerData = PlayerData(videoId, playlistId, channelId, keepQueue, position) val intent = Intent(context, OnlinePlayerService::class.java) - .putExtra(IntentData.videoId, videoId) - .putExtra(IntentData.playlistId, playlistId) - .putExtra(IntentData.channelId, channelId) - .putExtra(IntentData.position, position) - .putExtra(IntentData.keepQueue, keepQueue) + .putExtra(IntentData.playerData, playerData) // start the background mode as foreground service ContextCompat.startForegroundService(context, intent) diff --git a/app/src/main/java/com/github/libretube/helpers/DownloadHelper.kt b/app/src/main/java/com/github/libretube/helpers/DownloadHelper.kt index db02c067eb..a12e70820f 100644 --- a/app/src/main/java/com/github/libretube/helpers/DownloadHelper.kt +++ b/app/src/main/java/com/github/libretube/helpers/DownloadHelper.kt @@ -7,7 +7,7 @@ import androidx.core.content.ContextCompat import com.github.libretube.constants.IntentData import com.github.libretube.constants.PreferenceKeys import com.github.libretube.db.obj.DownloadItem -import com.github.libretube.services.DownloadData +import com.github.libretube.parcelable.DownloadData import com.github.libretube.services.DownloadService import java.nio.file.Path diff --git a/app/src/main/java/com/github/libretube/helpers/NavigationHelper.kt b/app/src/main/java/com/github/libretube/helpers/NavigationHelper.kt index 6475c5cb0d..5ce79cbff6 100644 --- a/app/src/main/java/com/github/libretube/helpers/NavigationHelper.kt +++ b/app/src/main/java/com/github/libretube/helpers/NavigationHelper.kt @@ -16,6 +16,7 @@ import com.github.libretube.constants.IntentData import com.github.libretube.constants.PreferenceKeys import com.github.libretube.enums.PlaylistType import com.github.libretube.extensions.toID +import com.github.libretube.parcelable.PlayerData import com.github.libretube.ui.fragments.AudioPlayerFragment import com.github.libretube.ui.fragments.PlayerFragment import com.github.libretube.ui.views.SingleViewTouchableMotionLayout @@ -53,7 +54,7 @@ object NavigationHelper { playlistId: String? = null, channelId: String? = null, keepQueue: Boolean = false, - timeStamp: Long? = null, + timestamp: Long = 0, forceVideo: Boolean = false, ) { if (videoId == null) return @@ -63,7 +64,7 @@ object NavigationHelper { BackgroundHelper.playOnBackground( context, videoId.toID(), - timeStamp, + timestamp, playlistId, channelId, keepQueue, @@ -74,13 +75,8 @@ object NavigationHelper { return } - val bundle = bundleOf( - IntentData.videoId to videoId.toID(), - IntentData.playlistId to playlistId, - IntentData.channelId to channelId, - IntentData.keepQueue to keepQueue, - IntentData.timeStamp to timeStamp, - ) + val playerData = PlayerData(videoId.toID(), playlistId, channelId, keepQueue, timestamp) + val bundle = bundleOf(IntentData.playerData to playerData) val activity = ContextHelper.unwrapActivity(context) activity.supportFragmentManager.commitNow { diff --git a/app/src/main/java/com/github/libretube/services/DownloadData.kt b/app/src/main/java/com/github/libretube/parcelable/DownloadData.kt similarity index 88% rename from app/src/main/java/com/github/libretube/services/DownloadData.kt rename to app/src/main/java/com/github/libretube/parcelable/DownloadData.kt index 886d0dfd3b..298157cb4c 100644 --- a/app/src/main/java/com/github/libretube/services/DownloadData.kt +++ b/app/src/main/java/com/github/libretube/parcelable/DownloadData.kt @@ -1,4 +1,4 @@ -package com.github.libretube.services +package com.github.libretube.parcelable import android.os.Parcelable import kotlinx.parcelize.Parcelize diff --git a/app/src/main/java/com/github/libretube/parcelable/PlayerData.kt b/app/src/main/java/com/github/libretube/parcelable/PlayerData.kt new file mode 100644 index 0000000000..2096225575 --- /dev/null +++ b/app/src/main/java/com/github/libretube/parcelable/PlayerData.kt @@ -0,0 +1,13 @@ +package com.github.libretube.parcelable + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize +data class PlayerData( + val videoId: String, + val playlistId: String? = null, + val channelId: String? = null, + val keepQueue: Boolean = false, + val timestamp: Long = 0 +) : Parcelable diff --git a/app/src/main/java/com/github/libretube/services/DownloadService.kt b/app/src/main/java/com/github/libretube/services/DownloadService.kt index 6b7e5d95b3..c656420f61 100644 --- a/app/src/main/java/com/github/libretube/services/DownloadService.kt +++ b/app/src/main/java/com/github/libretube/services/DownloadService.kt @@ -33,6 +33,7 @@ import com.github.libretube.helpers.DownloadHelper import com.github.libretube.helpers.DownloadHelper.getNotificationId import com.github.libretube.helpers.ImageHelper import com.github.libretube.obj.DownloadStatus +import com.github.libretube.parcelable.DownloadData import com.github.libretube.receivers.NotificationReceiver import com.github.libretube.receivers.NotificationReceiver.Companion.ACTION_DOWNLOAD_PAUSE import com.github.libretube.receivers.NotificationReceiver.Companion.ACTION_DOWNLOAD_RESUME diff --git a/app/src/main/java/com/github/libretube/services/OnlinePlayerService.kt b/app/src/main/java/com/github/libretube/services/OnlinePlayerService.kt index 336c103476..18746b876f 100644 --- a/app/src/main/java/com/github/libretube/services/OnlinePlayerService.kt +++ b/app/src/main/java/com/github/libretube/services/OnlinePlayerService.kt @@ -6,7 +6,6 @@ import android.os.Binder import android.os.Handler import android.os.IBinder import android.os.Looper -import android.util.Log import android.widget.Toast import androidx.core.app.NotificationCompat import androidx.core.app.ServiceCompat @@ -28,7 +27,7 @@ import com.github.libretube.constants.IntentData import com.github.libretube.constants.PLAYER_NOTIFICATION_ID import com.github.libretube.db.DatabaseHolder.Database import com.github.libretube.db.obj.WatchPosition -import com.github.libretube.extensions.TAG +import com.github.libretube.extensions.parcelableExtra import com.github.libretube.extensions.setMetadata import com.github.libretube.extensions.toID import com.github.libretube.helpers.PlayerHelper @@ -36,6 +35,7 @@ import com.github.libretube.helpers.PlayerHelper.checkForSegments import com.github.libretube.helpers.PlayerHelper.loadPlaybackParams import com.github.libretube.helpers.ProxyHelper import com.github.libretube.obj.PlayerNotificationData +import com.github.libretube.parcelable.PlayerData import com.github.libretube.util.NowPlayingNotification import com.github.libretube.util.PlayingQueue import kotlinx.coroutines.CoroutineScope @@ -117,27 +117,24 @@ class OnlinePlayerService : LifecycleService() { * Initializes the [player] with the [MediaItem]. */ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - try { - // reset the playing queue listeners - PlayingQueue.resetToDefaults() + // reset the playing queue listeners + PlayingQueue.resetToDefaults() + intent?.parcelableExtra(IntentData.playerData)?.let { playerData -> // get the intent arguments - videoId = intent?.getStringExtra(IntentData.videoId)!! - playlistId = intent.getStringExtra(IntentData.playlistId) - val position = intent.getLongExtra(IntentData.position, 0L) - val keepQueue = intent.getBooleanExtra(IntentData.keepQueue, false) + videoId = playerData.videoId + playlistId = playerData.playlistId // play the audio in the background - loadAudio(videoId, position, keepQueue) + loadAudio(playerData) PlayingQueue.setOnQueueTapListener { streamItem -> streamItem.url?.toID()?.let { playNextVideo(it) } } - if (PlayerHelper.watchPositionsAudio) updateWatchPosition() - } catch (e: Exception) { - Log.e(TAG(), e.toString()) - onDestroy() + if (PlayerHelper.watchPositionsAudio) { + updateWatchPosition() + } } return super.onStartCommand(intent, flags, startId) } @@ -158,15 +155,10 @@ class OnlinePlayerService : LifecycleService() { /** * Gets the video data and prepares the [player]. - * @param videoId The id of the video to play - * @param seekToPosition The position of the video to seek to - * @param keepQueue Whether to keep the queue or clear it instead */ - private fun loadAudio( - videoId: String, - seekToPosition: Long = 0, - keepQueue: Boolean = false, - ) { + private fun loadAudio(playerData: PlayerData) { + val (videoId, _, _, keepQueue, timestamp) = playerData + lifecycleScope.launch(Dispatchers.IO) { streams = runCatching { RetrofitInstance.api.getStreams(videoId) @@ -183,7 +175,7 @@ class OnlinePlayerService : LifecycleService() { } withContext(Dispatchers.Main) { - playAudio(seekToPosition) + playAudio(timestamp) } } } @@ -292,7 +284,7 @@ class OnlinePlayerService : LifecycleService() { this.videoId = nextVideo this.streams = null this.segments = emptyList() - loadAudio(videoId, keepQueue = true) + loadAudio(PlayerData(videoId, keepQueue = true)) } /** diff --git a/app/src/main/java/com/github/libretube/ui/activities/MainActivity.kt b/app/src/main/java/com/github/libretube/ui/activities/MainActivity.kt index b68735f071..35e1a7c179 100644 --- a/app/src/main/java/com/github/libretube/ui/activities/MainActivity.kt +++ b/app/src/main/java/com/github/libretube/ui/activities/MainActivity.kt @@ -28,7 +28,6 @@ import com.github.libretube.constants.IntentData import com.github.libretube.constants.PreferenceKeys import com.github.libretube.databinding.ActivityMainBinding import com.github.libretube.extensions.toID -import com.github.libretube.helpers.BackgroundHelper import com.github.libretube.helpers.NavBarHelper import com.github.libretube.helpers.NavigationHelper import com.github.libretube.helpers.NetworkHelper @@ -421,26 +420,26 @@ class MainActivity : BaseActivity() { intent?.getStringExtra(IntentData.channelId)?.let { navController.navigate( R.id.channelFragment, - bundleOf(IntentData.channelId to it), + bundleOf(IntentData.channelId to it) ) } intent?.getStringExtra(IntentData.channelName)?.let { navController.navigate( R.id.channelFragment, - bundleOf(IntentData.channelName to it), + bundleOf(IntentData.channelName to it) ) } intent?.getStringExtra(IntentData.playlistId)?.let { navController.navigate( R.id.playlistFragment, - bundleOf(IntentData.playlistId to it), + bundleOf(IntentData.playlistId to it) ) } intent?.getStringExtra(IntentData.videoId)?.let { NavigationHelper.navigateVideo( context = this, videoId = it, - timeStamp = intent?.getLongExtra(IntentData.timeStamp, 0L), + timestamp = intent.getLongExtra(IntentData.timeStamp, 0L) ) } diff --git a/app/src/main/java/com/github/libretube/ui/dialogs/DownloadDialog.kt b/app/src/main/java/com/github/libretube/ui/dialogs/DownloadDialog.kt index 564ee07fd9..8819c12850 100644 --- a/app/src/main/java/com/github/libretube/ui/dialogs/DownloadDialog.kt +++ b/app/src/main/java/com/github/libretube/ui/dialogs/DownloadDialog.kt @@ -22,7 +22,7 @@ import com.github.libretube.extensions.TAG import com.github.libretube.extensions.getWhileDigit import com.github.libretube.helpers.DownloadHelper import com.github.libretube.helpers.PreferenceHelper -import com.github.libretube.services.DownloadData +import com.github.libretube.parcelable.DownloadData import com.github.libretube.util.TextUtils import com.google.android.material.dialog.MaterialAlertDialogBuilder import kotlinx.coroutines.Dispatchers diff --git a/app/src/main/java/com/github/libretube/ui/fragments/AudioPlayerFragment.kt b/app/src/main/java/com/github/libretube/ui/fragments/AudioPlayerFragment.kt index 197ab7ef7b..7d884372e2 100644 --- a/app/src/main/java/com/github/libretube/ui/fragments/AudioPlayerFragment.kt +++ b/app/src/main/java/com/github/libretube/ui/fragments/AudioPlayerFragment.kt @@ -138,7 +138,7 @@ class AudioPlayerFragment : Fragment(), AudioPlayerOptions { NavigationHelper.navigateVideo( context = requireContext(), videoId = PlayingQueue.getCurrent()?.url?.toID(), - timeStamp = playerService?.player?.currentPosition?.div(1000), + timestamp = playerService?.player?.currentPosition?.div(1000) ?: 0, keepQueue = true, forceVideo = true, ) diff --git a/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt b/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt index 109b6edabe..ff53275719 100644 --- a/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt +++ b/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt @@ -70,6 +70,7 @@ import com.github.libretube.enums.PlayerEvent import com.github.libretube.enums.ShareObjectType import com.github.libretube.extensions.formatShort import com.github.libretube.extensions.hideKeyboard +import com.github.libretube.extensions.parcelable import com.github.libretube.extensions.setMetadata import com.github.libretube.extensions.toID import com.github.libretube.extensions.toastFromMainDispatcher @@ -86,6 +87,7 @@ import com.github.libretube.helpers.ProxyHelper import com.github.libretube.obj.PlayerNotificationData import com.github.libretube.obj.ShareData import com.github.libretube.obj.VideoResolution +import com.github.libretube.parcelable.PlayerData import com.github.libretube.services.DownloadService import com.github.libretube.ui.activities.MainActivity import com.github.libretube.ui.adapters.ChaptersAdapter @@ -137,11 +139,12 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions { /** * Video information passed by the intent */ - private var videoId: String? = null + private lateinit var playerData: PlayerData + private lateinit var videoId: String private var playlistId: String? = null private var channelId: String? = null private var keepQueue: Boolean = false - private var timeStamp: Long? = null + private var timeStamp: Long = 0 /** * Video information fetched at runtime @@ -234,13 +237,12 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - arguments?.let { - videoId = it.getString(IntentData.videoId)!!.toID() - playlistId = it.getString(IntentData.playlistId) - channelId = it.getString(IntentData.channelId) - keepQueue = it.getBoolean(IntentData.keepQueue, false) - timeStamp = it.getLong(IntentData.timeStamp, 0L) - } + val playerData = requireArguments().parcelable(IntentData.playerData)!! + videoId = playerData.videoId + playlistId = playerData.playlistId + channelId = playerData.channelId + keepQueue = playerData.keepQueue + timeStamp = playerData.timestamp // broadcast receiver for PiP actions context?.registerReceiver( @@ -390,11 +392,10 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions { } binding.commentsToggle.setOnClickListener { - videoId ?: return@setOnClickListener // set the max height to not cover the currently playing video commentsViewModel.handleLink = this::handleLink commentsViewModel.maxHeight = binding.root.height - binding.player.height - commentsViewModel.videoId = videoId + commentsViewModel.videoId = playerData.videoId CommentsSheet().show(childFragmentManager) } @@ -434,7 +435,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions { if (!this::streams.isInitialized) return@setOnClickListener val shareDialog = ShareDialog( - videoId!!, + videoId, ShareObjectType.VIDEO, ShareData( currentVideo = streams.title, @@ -487,7 +488,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions { BackgroundHelper.stopBackgroundPlay(requireContext()) BackgroundHelper.playOnBackground( requireContext(), - videoId!!, + videoId, exoPlayer.currentPosition, playlistId, channelId, @@ -648,7 +649,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions { C.TIME_UNSET ) ) return - val watchPosition = WatchPosition(videoId!!, exoPlayer.currentPosition) + val watchPosition = WatchPosition(videoId, exoPlayer.currentPosition) CoroutineScope(Dispatchers.IO).launch { Database.watchPositionDao().insert(watchPosition) } @@ -685,7 +686,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions { lifecycleScope.launch(Dispatchers.IO) { streams = try { - RetrofitInstance.api.getStreams(videoId!!) + RetrofitInstance.api.getStreams(videoId) } catch (e: IOException) { context?.toastFromMainDispatcher(R.string.unknown_error, Toast.LENGTH_LONG) return@launch @@ -700,18 +701,18 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions { if (PlayingQueue.isEmpty()) { lifecycleScope.launch(Dispatchers.IO) { if (playlistId != null) { - PlayingQueue.insertPlaylist(playlistId!!, streams.toStreamItem(videoId!!)) + PlayingQueue.insertPlaylist(playlistId!!, streams.toStreamItem(videoId)) } else if (channelId != null) { - PlayingQueue.insertChannel(channelId!!, streams.toStreamItem(videoId!!)) + PlayingQueue.insertChannel(channelId!!, streams.toStreamItem(videoId)) } else { - PlayingQueue.updateCurrent(streams.toStreamItem(videoId!!)) + PlayingQueue.updateCurrent(streams.toStreamItem(videoId)) if (PlayerHelper.autoInsertRelatedVideos) { PlayingQueue.add(*streams.relatedStreams.toTypedArray()) } } } } else { - PlayingQueue.updateCurrent(streams.toStreamItem(videoId!!)) + PlayingQueue.updateCurrent(streams.toStreamItem(videoId)) } if (PreferenceHelper.getBoolean(PreferenceKeys.AUTO_FULLSCREEN_SHORTS, false)) { @@ -761,7 +762,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions { // add the video to the watch history if (PlayerHelper.watchHistoryEnabled) { - DatabaseHelper.addToWatchHistory(videoId!!, streams) + DatabaseHelper.addToWatchHistory(videoId, streams) } } } @@ -777,7 +778,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions { if (categories.isEmpty()) return@runCatching segments = RetrofitInstance.api.getSegments( - videoId!!, + videoId, JsonHelper.json.encodeToString(categories), ).segments if (segments.isEmpty()) return@runCatching @@ -816,7 +817,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions { // browse the watch positions val position = try { runBlocking { - Database.watchPositionDao().findById(videoId!!)?.position + Database.watchPositionDao().findById(videoId)?.position } } catch (e: Exception) { return @@ -832,11 +833,11 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions { */ private fun trySeekToTimeStamp() { // support for time stamped links - timeStamp?.let { - if (it != 0L) exoPlayer.seekTo(it * 1000) + if (timeStamp != 0L) { + exoPlayer.seekTo(timeStamp * 1000) } // delete the time stamp because it already got consumed - timeStamp = null + timeStamp = 0 } // used for autoplay and skipping to next video @@ -1001,7 +1002,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions { if (streams.duration <= 0) { Toast.makeText(context, R.string.cannotDownload, Toast.LENGTH_SHORT).show() } else if (!DownloadService.IS_DOWNLOAD_RUNNING) { - val newFragment = DownloadDialog(videoId!!) + val newFragment = DownloadDialog(videoId) newFragment.show(childFragmentManager, DownloadDialog::class.java.name) } else { Toast.makeText(context, R.string.dlisinprogress, Toast.LENGTH_SHORT) @@ -1034,7 +1035,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions { ) binding.relPlayerSave.setOnClickListener { - AddToPlaylistDialog(videoId!!).show( + AddToPlaylistDialog(videoId).show( childFragmentManager, AddToPlaylistDialog::class.java.name, ) @@ -1379,7 +1380,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions { streams.uploader, streams.thumbnailUrl, ) - nowPlayingNotification.updatePlayerNotification(videoId!!, playerNotificationData) + nowPlayingNotification.updatePlayerNotification(videoId, playerNotificationData) } /** @@ -1458,7 +1459,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions { override fun onStatsClicked() { if (!this::streams.isInitialized) return - StatsDialog(exoPlayer, videoId ?: return) + StatsDialog(exoPlayer, videoId) .show(childFragmentManager, null) }