Android cleaning up chromecast player and more failed attempts

This commit is contained in:
advplyr 2022-04-10 16:46:09 -05:00
parent e5c8d5d4d4
commit ef65b4c278
7 changed files with 112 additions and 51 deletions

View file

@ -11,6 +11,7 @@ import com.google.android.gms.cast.framework.media.CastMediaOptions
class CastOptionsProvider : OptionsProvider {
override fun getCastOptions(context: Context): CastOptions {
Log.d("CastOptionsProvider", "getCastOptions")
var appId = "FD1F76C5"
return CastOptions.Builder()
.setReceiverApplicationId(CastMediaControlIntent.DEFAULT_MEDIA_RECEIVER_APPLICATION_ID).setCastMediaOptions(
CastMediaOptions.Builder()

View file

@ -9,6 +9,9 @@ import com.fasterxml.jackson.annotation.JsonIgnore
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
import com.google.android.exoplayer2.MediaItem
import com.google.android.exoplayer2.MediaMetadata
import com.google.android.gms.cast.MediaInfo
import com.google.android.gms.cast.MediaQueueItem
import com.google.android.gms.common.images.WebImage
// TODO: enum or something in kotlin?
val PLAYMETHOD_DIRECTPLAY = 0
@ -135,12 +138,41 @@ class PlaybackSession(
var mediaMetadata = this.getExoMediaMetadata(audioTrack)
var mediaUri = this.getContentUri(audioTrack)
var mimeType = audioTrack.mimeType
var mediaItem = MediaItem.Builder().setUri(mediaUri).setMediaMetadata(mediaMetadata).setMimeType(mimeType).build()
var queueItem = getQueueItem(audioTrack) // Queue item used in exo player CastManager
var mediaItem = MediaItem.Builder().setUri(mediaUri).setTag(queueItem).setMediaMetadata(mediaMetadata).setMimeType(mimeType).build()
mediaItems.add(mediaItem)
}
return mediaItems
}
@JsonIgnore
fun getCastMediaMetadata(audioTrack:AudioTrack):com.google.android.gms.cast.MediaMetadata {
var castMetadata = com.google.android.gms.cast.MediaMetadata(com.google.android.gms.cast.MediaMetadata.MEDIA_TYPE_AUDIOBOOK_CHAPTER)
castMetadata.addImage(WebImage(getCoverUri()))
castMetadata.putString(com.google.android.gms.cast.MediaMetadata.KEY_TITLE, displayTitle)
castMetadata.putString(com.google.android.gms.cast.MediaMetadata.KEY_ARTIST, displayAuthor)
castMetadata.putInt(com.google.android.gms.cast.MediaMetadata.KEY_TRACK_NUMBER, audioTrack.index)
return castMetadata
}
@JsonIgnore
fun getQueueItem(audioTrack:AudioTrack):MediaQueueItem {
var castMetadata = getCastMediaMetadata(audioTrack)
var mediaUri = getContentUri(audioTrack)
var mediaInfoBuilder = MediaInfo.Builder(mediaUri.toString())
mediaInfoBuilder.setContentUrl(mediaUri.toString())
mediaInfoBuilder.setMetadata(castMetadata)
mediaInfoBuilder.setContentType(audioTrack.mimeType)
var mediaInfo = mediaInfoBuilder.build()
var queueItem = MediaQueueItem.Builder(mediaInfo)
queueItem.setItemId(audioTrack.index)
queueItem.setPlaybackDuration(audioTrack.duration)
return queueItem.build()
}
@JsonIgnore
fun clone():PlaybackSession {
return PlaybackSession(id,userId,libraryItemId,episodeId,mediaType,mediaMetadata,chapters,displayTitle,displayAuthor,coverPath,duration,playMethod,startedAt,updatedAt,timeListening,audioTracks,currentTime,libraryItem,localLibraryItem,serverConnectionConfigId,serverAddress)

View file

@ -9,17 +9,19 @@ import androidx.mediarouter.app.MediaRouteChooserDialog
import androidx.mediarouter.media.MediaRouteSelector
import androidx.mediarouter.media.MediaRouter
import com.getcapacitor.PluginCall
import com.google.android.exoplayer2.MediaItem
import com.google.android.exoplayer2.ext.cast.CastPlayer
import com.google.android.exoplayer2.ext.cast.MediaItemConverter
import com.google.android.exoplayer2.ext.cast.SessionAvailabilityListener
import com.google.android.gms.cast.Cast
import com.google.android.gms.cast.CastDevice
import com.google.android.gms.cast.CastMediaControlIntent
import com.google.android.gms.cast.MediaQueueItem
import com.google.android.gms.cast.framework.*
import org.json.JSONObject
import java.util.ArrayList
class CastManager constructor(playerNotificationService:PlayerNotificationService) {
private val tag = "SleepTimerManager"
private val tag = "CastManager"
private val playerNotificationService:PlayerNotificationService = playerNotificationService
private var newConnectionListener: SessionListener? = null
@ -291,6 +293,22 @@ class CastManager constructor(playerNotificationService:PlayerNotificationServic
}
}
inner class CustomConverter : MediaItemConverter {
override fun toMediaQueueItem(mediaItem: MediaItem): MediaQueueItem {
// The MediaQueueItem you build is expected to be in the tag.
var queueItem = (mediaItem.playbackProperties!!.tag as MediaQueueItem?)!!
Log.d(tag, "Test toMediaQueueItem ${queueItem.media!!.contentUrl} | ${queueItem.playbackDuration} | ${queueItem.itemId}")
return queueItem
}
override fun toMediaItem(mediaQueueItem: MediaQueueItem): MediaItem {
return MediaItem.Builder()
.setUri(mediaQueueItem.media!!.contentUrl)
.setTag(mediaQueueItem)
.build()
}
}
private fun listenForConnection(callback: ConnectionCallback) {
// We should only ever have one of these listeners active at a time, so remove previous
getSessionManager()?.removeSessionManagerListener(newConnectionListener, CastSession::class.java)
@ -302,7 +320,8 @@ class CastManager constructor(playerNotificationService:PlayerNotificationServic
try {
val castContext = CastContext.getSharedInstance(mainActivity)
playerNotificationService.castPlayer = CastPlayer(castContext).apply {
playerNotificationService.castPlayer = CastPlayer(castContext, CustomConverter()).apply {
setSessionAvailabilityListener(CastSessionAvailabilityListener())
addListener(PlayerListener(playerNotificationService))
}

View file

@ -33,6 +33,7 @@ import com.google.android.exoplayer2.ext.mediasession.TimelineQueueNavigator
import com.google.android.exoplayer2.source.MediaSource
import com.google.android.exoplayer2.source.ProgressiveMediaSource
import com.google.android.exoplayer2.source.hls.HlsMediaSource
import com.google.android.exoplayer2.ui.PlayerControlView
import com.google.android.exoplayer2.ui.PlayerNotificationManager
import com.google.android.exoplayer2.upstream.*
import okhttp3.OkHttpClient
@ -184,8 +185,6 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
currentPlayer = mPlayer
var client: OkHttpClient = OkHttpClient()
// Initialize API
apiHandler = ApiHandler(ctx)
@ -220,9 +219,6 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
isActive = true
}
Log.d(tag, "Media Session Set")
val mediaController = MediaControllerCompat(ctx, mediaSession.sessionToken)
// This is for Media Browser
@ -293,10 +289,9 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
var metadata = playbackSession.getMediaMetadataCompat()
mediaSession.setMetadata(metadata)
var mediaItems = playbackSession.getMediaItems()
if (mPlayer == currentPlayer) {
var mediaSource:MediaSource
if (playbackSession.isLocal) {
@ -316,24 +311,25 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
}
mPlayer.setMediaSource(mediaSource)
} else if (castPlayer != null) {
castPlayer?.addMediaItem(mediaItems[0]) // TODO: Media items never actually get added, not sure what is going on....
Log.d(tag, "Cast Player ADDED MEDIA ITEM ${castPlayer?.currentMediaItem} | ${castPlayer?.duration} | ${castPlayer?.mediaItemCount}")
}
// Add remaining media items if multi-track
if (mediaItems.size > 1) {
mPlayer.addMediaItems(mediaItems.subList(1, mediaItems.size))
Log.d(tag, "mPlayer total media items ${mPlayer.mediaItemCount}")
currentPlayer.addMediaItems(mediaItems.subList(1, mediaItems.size))
Log.d(tag, "currentPlayer total media items ${currentPlayer.mediaItemCount}")
var currentTrackIndex = playbackSession.getCurrentTrackIndex()
var currentTrackTime = playbackSession.getCurrentTrackTimeMs()
Log.d(tag, "mPlayer current track index $currentTrackIndex & current track time $currentTrackTime")
mPlayer.seekTo(currentTrackIndex, currentTrackTime)
Log.d(tag, "currentPlayer current track index $currentTrackIndex & current track time $currentTrackTime")
currentPlayer.seekTo(currentTrackIndex, currentTrackTime)
} else {
mPlayer.seekTo(playbackSession.currentTimeMs)
}
} else if (castPlayer != null) {
//// var mediaQueue = currentAudiobookStreamData!!.getCastQueue()
// // TODO: Start position will need to be adjusted if using multi-track queue
//// castPlayer?.setMediaItems(mediaQueue, 0, 0)
currentPlayer.seekTo(playbackSession.currentTimeMs)
}
Log.d(tag, "Prepare complete for session ${currentPlaybackSession?.displayTitle} | ${currentPlayer.mediaItemCount}")
currentPlayer.playWhenReady = playWhenReady
currentPlayer.setPlaybackSpeed(1f) // TODO: Playback speed should come from settings
currentPlayer.prepare()
@ -349,9 +345,9 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
mediaSessionConnector.setPlayer(mPlayer)
mPlayer
}
if (currentPlaybackSession != null) {
Log.d(tag, "switchToPlayer: Initing current ab stream data")
preparePlayer(currentPlaybackSession!!, false)
currentPlaybackSession?.let {
Log.d(tag, "switchToPlayer: Preparing current playback session ${it.displayTitle}")
preparePlayer(it, false)
}
}
@ -404,6 +400,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
if (currentPlayer == castPlayer) {
Log.d(tag, "CAST Player set on play ${currentPlayer.isLoading} || ${currentPlayer.duration} | ${currentPlayer.currentPosition}")
}
currentPlayer.play()
}
@ -411,6 +408,16 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
currentPlayer.pause()
}
fun playPause():Boolean {
return if (currentPlayer.isPlaying) {
pause()
false
} else {
play()
true
}
}
fun seekPlayer(time: Long) {
if (currentPlayer.mediaItemCount > 1) {
currentPlaybackSession?.currentTime = time / 1000.0

View file

@ -147,6 +147,14 @@ class AbsAudioPlayer : Plugin() {
}
}
@PluginMethod
fun playPause(call: PluginCall) {
Handler(Looper.getMainLooper()).post() {
var playing = playerNotificationService.playPause()
call.resolve(JSObject("{\"playing\":$playing}"))
}
}
@PluginMethod
fun seekPlayer(call: PluginCall) {
var time:Long = call.getString("timeMs", "0")!!.toLong()
@ -246,7 +254,7 @@ class AbsAudioPlayer : Plugin() {
@PluginMethod
fun requestSession(call: PluginCall) {
Log.d(tag, "CAST REQUEST SESSION PLUGIN")
call.resolve()
playerNotificationService.castManager.requestSession(mainActivity, object : CastManager.RequestSessionCallback() {
override fun onError(errorCode: Int) {
Log.e(tag, "CAST REQUEST SESSION CALLBACK ERROR $errorCode")

View file

@ -109,7 +109,7 @@ export default {
playbackSession: null,
// Others
showChapterModal: false,
showCastBtn: false,
showCastBtn: true,
showFullscreen: false,
totalDuration: 0,
currentPlaybackRate: 1,
@ -455,15 +455,9 @@ export default {
}
this.seek(time)
},
playPauseClick() {
async playPauseClick() {
if (this.isLoading) return
if (this.isPaused) {
console.log('playPause PLAY')
this.play()
} else {
console.log('playPause PAUSE')
this.pause()
}
this.isPlaying = !!((await AbsAudioPlayer.playPause()) || {}).playing
},
play() {
AbsAudioPlayer.playPlayer()

View file

@ -120,7 +120,7 @@ export default {
return this.media.coverPath || this.placeholderUrl
},
hasCover() {
return !!this.media.coverPath
return !!this.media.coverPath || this.localCover
},
sizeMultiplier() {
var baseSize = this.squareAspectRatio ? 192 : 120