Ksenia
Ksenia

Reputation: 3753

How to reinitialize ExoPlayer after releasing?

I have ExoPlayerWrapper class which is wrapper for ExoPlayer and is singleton injected by Dagger. Init block in ExoPlayerWrapper class looks in the following way:

@Singleton
class ExoPlayerWrapper @Inject constructor(
    context: Context,
    userAgentInfo: UserAgentInfo
) {
    private val exoPlayer: ExoPlayer
    private val httpDataSource: HttpDataSource
    private val mediaSourceFactory: ExtractorMediaSource.Factory

    override val exoPlayerInstance: ExoPlayer
        get() = exoPlayer

   init {
        ...
        exoPlayer = ExoPlayerFactory.newSimpleInstance(renderersFactory, trackSelector)
        httpDataSource = CustomHttpDataSource(userAgentInfo.userAgent, null)
        mediaSourceFactory = ExtractorMediaSource.Factory { httpDataSource }
        state = Player.STATE_IDLE
    }

   override fun playFromUrl(uri: Uri, headers: Map<String, String>) {
        reset()
        ...
        val mediaSource = mediaSourceFactory.createMediaSource(uri)
        exoPlayer.prepare(mediaSource)
        exoPlayer.playWhenReady = true
    }

    override fun pause() {
        exoPlayer.playWhenReady = false
    }

    override fun reset() {
       stop()
       state = Player.STATE_IDLE
    }

    override fun stop() {
       exoPlayer.stop()
       exoPlayer.seekTo(0)
    }

    override fun seekTo(position: Long) {
       exoPlayer.seekTo(position)
    }

    ...

    override fun release() {
        exoPlayer.release()
        state = Player.STATE_RELEASED
    }

And in onCreate() method of Activity I have the following code:

public override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_video_player)
    ...
    if (savedInstanceState != null) {
        initialized = savedInstanceState.getBoolean(INITIALIZED)
    } 
    if (!initialized) {
        val uri = Uri.parse(attachedVideo?.uri)
        player.playFromUrl(uri, sessionStore.sessionHeaders)
        videoView.requestFocus()
        initialized = true
    }

    videoView.player = player.exoPlayerInstance

    backBtn.setOnClickListener{ _ ->
        player.release()
        finish()
    }
}

But in this case I can play only one video after click on backBtn button, other videos after that aren't played until I close app and reopen app again. And if I change backBtn's OnClickListener in the following way:

backBtn.setOnClickListener{ _ ->
    player.pause()
    finish()
}

all works fine, other videos are played after click on backBtn button. So it seems to be problem with reinitializing ExoPlayer after release() method invocation. And how correctly to reinitialize ExoPlayer after releasing?

UPD And after release() invocation and after attempt to open video again I see the following error in Logcat:

java.lang.IllegalStateException: Handler (android.os.Handler) {81fa8ef} sending message to a Handler on a dead thread
    at android.os.MessageQueue.enqueueMessage(MessageQueue.java:545)
    at android.os.Handler.enqueueMessage(Handler.java:661)
    at android.os.Handler.sendMessageAtTime(Handler.java:630)
    at android.os.Handler.sendMessageDelayed(Handler.java:600)
    at android.os.Handler.sendMessage(Handler.java:537)
    at android.os.Message.sendToTarget(Message.java:418)
    at com.google.android.exoplayer2.ExoPlayerImplInternal.stop(ExoPlayerImplInternal.java:207)
    at com.google.android.exoplayer2.ExoPlayerImpl.stop(ExoPlayerImpl.java:357)
    at com.google.android.exoplayer2.SimpleExoPlayer.stop(SimpleExoPlayer.java:777)
    at com.google.android.exoplayer2.SimpleExoPlayer.stop(SimpleExoPlayer.java:772)
    at package.ExoPlayerWrapper.stop(ExoPlayerWrapper.kt:xx)
    at package.ExoPlayerWrapper.reset(ExoPlayerWrapper.kt:xx)
    at package.ExoPlayerWrapper.playFromUrl(ExoPlayerWrapper.kt:xx)
    at package.VideoPlayerActivity.onCreate(VideoPlayerActivity.kt:xx)

Upvotes: 3

Views: 8994

Answers (2)

Rimov
Rimov

Reputation: 81

The issue arises from trying to use a player whose resources have already been released. Because:

exoPlayer = ExoPlayerFactory.newSimpleInstance(renderersFactory, trackSelector)

only gets called once, during the initialization of ExoPlayerWrapper. If your activity is not restarted, then that instance of ExoPlayerWrapper sticks around with the released player.

Either create a new instance of ExoPlayerWrapper whenever you go to play your video, or create a player initialization method inside ExoPlayerWrapper, which you can call just before playing the video.

Upvotes: 2

Magudesh
Magudesh

Reputation: 449

For your requirement no need to use release method. If you are using this method you should reinitialize exoplayer again.

You can use stop() method to stop the exoplayer.

Upvotes: 0

Related Questions