I am using a SimpleExoPlayer in a RecyclerView and sometimes there is an error when calling
simplePlayer.setPlayWhenReady(true);
The video player remains blank and the moments when the issue appears are not always the same (I did not find an exact way to simulate this)
Exception:
java.lang.IllegalStateException: Handler (android.os.Handler) {edbfbdd} sending message to a Handler on a dead thread
at android.os.MessageQueue.enqueueMessage(MessageQueue.java:545)
at android.os.Handler.enqueueMessage(Handler.java:662)
at android.os.Handler.sendMessageAtTime(Handler.java:631)
at android.os.Handler.sendMessageDelayed(Handler.java:601)
at android.os.Handler.sendMessage(Handler.java:538)
at android.os.Message.sendToTarget(Message.java:418)
at com.google.android.exoplayer2.ExoPlayerImplInternal.setPlayWhenReady(ExoPlayerImplInternal.java:183)
at com.google.android.exoplayer2.ExoPlayerImpl.setPlayWhenReady(ExoPlayerImpl.java:245)
at com.google.android.exoplayer2.SimpleExoPlayer.updatePlayWhenReady(SimpleExoPlayer.java:1188)
at com.google.android.exoplayer2.SimpleExoPlayer.setPlayWhenReady(SimpleExoPlayer.java:896)
My code runs inside a custom view (updated in recycler view adapter):
MyView h = this;
h.playerView = new PlayerView(getContext());
h.playerView.setVisibility(View.GONE);
h.postFrameLayout.addView(h.playerView, 0);
h.postFrameLayout.getLayoutParams().width = swidth;
h.postFrameLayout.getLayoutParams().height = (int) (swidth );
h.playerView.getLayoutParams().width = swidth;
h.playerView.getLayoutParams().height = (int) (swidth );
if (player != null){
player.release();
}
DefaultLoadControl loadControl = new DefaultLoadControl.Builder()
.setBufferDurationsMs(1100, 2000, 1000, 1000).createDefaultLoadControl();
final SimpleExoPlayer simplePlayer = ExoPlayerFactory.newSimpleInstance(getContext(), trackSelector, loadControl);
h.playerView.setUseController(false);
h.playerView.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FIXED_WIDTH);
h.playerView.setPlayer(simplePlayer);
simplePlayer.addListener(new Player.EventListener() {
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if (playbackState == Player.STATE_ENDED) {
h.videoPlay.setVisibility(View.VISIBLE);
h.postImage.setVisibility(View.VISIBLE);
simplePlayer.setPlayWhenReady(false);
simplePlayer.seekTo(0);
}
}
});
Uri uri = Uri.parse(videoUrl);
final MediaSource audioSource = new ExtractorMediaSource.Factory(dataSourceFactory)
.createMediaSource(uri);
simplePlayer.prepare(audioSource);
h.player = simplePlayer;
h.videoPlay.setVisibility(View.VISIBLE);
h.videoPlay.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
displayArticles(false, post.getPhotoItems(), h);
h.videoPlay.setVisibility(View.GONE);
h.postImage.setVisibility(View.GONE);
h.playerView.setVisibility(View.VISIBLE);
simplePlayer.setPlayWhenReady(true);
}
});
I release the player on detaching from the window (when recycler view calls onDetachedFromWindow() on my custom view):
if (player != null) {
videoPlay.setVisibility(View.VISIBLE);
postImage.setVisibility(View.VISIBLE);
player.release();
player = null;
}
Is there a way to avoid this issue or make retries when the player is started?
I have same problem when I try to use ..exoplayer2.ui.PlayerView class. There is not problem with ..exoplayer2.ui.PlayerControlView. this is my code:
public static void setUp(Context context){
ExoPlayerTool.context = context;
player = new SimpleExoPlayer.Builder(context).build();
dataSourceFactory = new DefaultDataSourceFactory(context,
Util.getUserAgent(context, "SingerApp"));
}
public static void setSource(String link){
Uri uri = Uri.parse(link);
MediaSource videoSource = new ProgressiveMediaSource.Factory(dataSourceFactory).createMediaSource(uri);
player.addListener(playerListener);
player.prepare(videoSource);
player.setPlayWhenReady(true);
}
I am calling setup()
function once, and setSource()
function every time I want to change source.
When i want to turn off music I call player.release();
and after release the setSource()
, gives same error on player.prepare(videoSource);
line.
I was able to fix the issue by creating new SimpleExoPlayer on every source change. code looks like this:
public static void setSource(String link){
Uri uri = Uri.parse(link);
MediaSource videoSource = new ProgressiveMediaSource.Factory(dataSourceFactory).createMediaSource(uri);
player.release();
player = new SimpleExoPlayer.Builder(context).build();
player.addListener(playerListener);
player.prepare(videoSource);
player.setPlayWhenReady(true);
}
I don't know how optimized this solution is but better than not releasing player at all.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With