androidexoplayerandroid-media3

PlayerView has a black screen


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 🤣.


Solution

  • I added the video settings code to binding.vv.post{} and it solved my problem.