media3 ExoPlayer в RecyclerView
Всем привет, подскажите, пожалуйста, как правильно реализовать управление медиа файлами. У меня есть приложение - чат, в котором отображаются голосовые сообщения и MediaSessionService реализованный согласно документации. На данный момент при воспроизведении одного голосового, включаются все голосовые, которые находятся в зоне видимости экрана и воспроизводится один медиафайл. Подскажите, пожалуйста, как правильно настроить viewHolder что бы для каждого голосового был свой медиафайл? Мой Service:
class PlayerService : MediaSessionService(),MediaSession.Callback {
companion object {
private val _isPlay = MutableStateFlow<Boolean>(false)
val isPlay: StateFlow<Boolean> = _isPlay
var currentVoiceName: String? = null
}
private var mediaSession: MediaSession? = null
override fun onCreate() {
super.onCreate()
val exoPlayer =
ExoPlayer.Builder(applicationContext, DefaultRenderersFactory(applicationContext))
.setLoadControl(
DefaultLoadControl.Builder()
.setPrioritizeTimeOverSizeThresholds(false).build()
)
.setTrackSelector(
DefaultTrackSelector(
applicationContext,
AdaptiveTrackSelection.Factory()
)
)
.setMediaSourceFactory(
ProgressiveMediaSource.Factory(
CacheDataSource.Factory()
.setCache(AppCommunity.cache)
.setUpstreamDataSourceFactory(
DefaultHttpDataSource.Factory()
.setUserAgent("Exoplayer")
)
.setFlags(CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR)
)
)
.build()
mediaSession = MediaSession.Builder(this, exoPlayer).setCallback(this).build()
exoPlayer.addListener(object : Player.Listener {
override fun onPlaybackStateChanged(playbackState: Int) {
_isPlay.value = !(playbackState == Player.STATE_ENDED && !exoPlayer.isPlaying)
Timber.d("IsPlay = ${_isPlay.value}")
if (!_isPlay.value) {
currentVoiceName = null
mediaSession?.player?.clearMediaItems()
}
super.onPlaybackStateChanged(playbackState)
}
override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) {
currentVoiceName = mediaItem?.mediaMetadata?.artist?.toString()
super.onMediaItemTransition(mediaItem, reason)
}
})
}
override fun onTaskRemoved(rootIntent: Intent?) {
val player = mediaSession?.player!!
if (!player.playWhenReady
|| player.mediaItemCount == 0
|| player.playbackState == Player.STATE_ENDED
) stopSelf()
}
override fun onDestroy() {
super.onDestroy()
mediaSession?.run {
player.release()
release()
mediaSession = null
}
}
override fun onGetSession(controllerInfo: MediaSession.ControllerInfo): MediaSession? {
return mediaSession
}
override fun onConnect(
session: MediaSession,
controller: MediaSession.ControllerInfo
): MediaSession.ConnectionResult {
Timber.d(controller.toString())
return super.onConnect(session, controller)
}
}
мой viewHolder
private var controllerFuture: ListenableFuture<MediaController>? = null
override fun onBinding(item: MessageItem) {
super.onBinding(item)
if (item !is MessageItem.ContentMessage)
return
binding.time.text = item.createDateAt
if (item.editDateAt != null) {
binding.time.text = itemView.context.getString(R.string.change_in, item.editDateAt)
}
if (item.itemMessageState == MessageState.DISPLAYED)
binding.checkMarkers.setImageResource(R.drawable.ic_check_marks_done)
else binding.checkMarkers.setImageResource(R.drawable.ic_check_send)
val mediaItem = MediaItem.Builder()
.setUri(item.listContent[0].uri)
.setMediaId(item.itemMessageId)
.setMediaMetadata(
MediaMetadata.Builder()
.setArtist(item.userName)
.setTitle(itemView.context.getString(R.string.voice))
.build()
)
val sessionToken = SessionToken(itemView.context, ComponentName(itemView.context, PlayerService::class.java))
controllerFuture = MediaController.Builder(itemView.context, sessionToken).buildAsync()
controllerFuture!!.addListener(
{
with(controllerFuture!!.get()) {
addMediaItem(mediaItem.build())
binding.exoplayerView.player = this
playWhenReady = false
prepare()
},
MoreExecutors.directExecutor()
)
}
private fun releasePlayer() {
binding.exoplayerView.player?.release()
binding.exoplayerView.player = null
controllerFuture?.let { MediaController.releaseFuture(it) }
}
override fun onDestroyView() {
super.onDestroyView()
Timber.d("onDestroyView")
releasePlayer()
}