I'm building a video player using ExoPlayer
. Sometimes, the PlayerView
has a black screen when I finish
the activity and re-open it. If I press the play/pause
button, the PlayerView
stays black but if I press the seek to next/previous 5s
button then the video is played. But I want to play the video when it's ready and hide the controller.
Here is my activity:
class PreviewActivity : BaseActivity<ActivityPreviewBinding, ActivityPreviewViewModel>() {
override fun getViewBinding(): ActivityPreviewBinding =
ActivityPreviewBinding.inflate(layoutInflater)
override fun getViewModelClass(): Class<ActivityPreviewViewModel> =
ActivityPreviewViewModel::class.java
@OptIn(UnstableApi::class)
override fun setupListener() {
binding.apply {
vv.player?.addListener(object : Player.Listener {
override fun onIsPlayingChanged(isPlaying: Boolean) {
Log.d(TAG, "[onIsPlayingChanged] IsPlaying: $isPlaying")
if (!isPlaying) {
vv.player?.play()
}
}
override fun onPlayerError(error: PlaybackException) {
super.onPlayerError(error)
Log.e(TAG, "[onPlayerError] Error: ${error.message}", error)
}
override fun onPlaybackStateChanged(playbackState: Int) {
super.onPlaybackStateChanged(playbackState)
Log.d(TAG, "[onPlaybackStateChanged] PlaybackState: $playbackState")
}
})
}
}
override fun setupViews() {
val bundle = intent.extras
val videoPath = bundle?.getString(BUNDLE_VIDEO_PATH)
setupVideo(videoPath)
}
@OptIn(UnstableApi::class)
private fun setupVideo(videoPath: String?) {
try {
binding.vv.apply {
val uri = Uri.parse(videoPath)
val mediaItem = MediaItem.fromUri(uri)
val exoPlayer = ExoPlayer.Builder(this@PreviewActivity).build()
exoPlayer.repeatMode = ExoPlayer.REPEAT_MODE_ONE
exoPlayer.playWhenReady = true
exoPlayer.addMediaItem(mediaItem)
exoPlayer.prepare()
exoPlayer.addAnalyticsListener(EventLogger())
useController = false
resizeMode = RESIZE_MODE_ZOOM
player = exoPlayer
}
} catch (e: Exception) {
e.printStackTrace()
}
}
override fun onDestroy() {
super.onDestroy()
binding.vv.player?.clearMediaItems()
binding.vv.player?.clearVideoSurface()
binding.vv.player?.release()
}
companion object {
const val BUNDLE_VIDEO_PATH = "videoPath"
private const val ONE_SECOND = 1000L
private const val TAG = "PreviewActivity"
}
}
Both setupListener()
and setupViews()
are called at onCreate()
func.
When I was trying to log the states of the Player
, I realize that if video is played, the playbackState
is changed to 3
which is STATE_READY
and isPlaying == true
. But if the screen is black, the playbackState
is changed to 2
which is STATE_BUFFERING
after STATE_READY
and isPlaying == false
without any exception.
2024-10-11 15:46:30.799 PreviewActivity D [onPlaybackStateChanged] PlaybackState: 3
2024-10-11 15:46:30.800 PreviewActivity D [onIsPlayingChanged] IsPlaying: true
2024-10-11 15:46:30.817 ViewRootIm...wActivity] I MSG_WINDOW_FOCUS_CHANGED 1 1
2024-10-11 15:46:35.707 PreviewActivity D [onPlaybackStateChanged] PlaybackState: 2
2024-10-11 15:46:35.708 PreviewActivity D [onIsPlayingChanged] IsPlaying: false
So I try to vv.player?.play()
when isPlaying == false
but it's not working 🤣.
I added the video settings code to binding.vv.post{}
and it solved my problem.