【问题标题】:ExoPlayer - java.lang.IllegalStateException: sending message to a Handler on a dead threadExoPlayer - java.lang.IllegalStateException:向死线程上的处理程序发送消息
【发布时间】:2019-08-30 17:10:36
【问题描述】:

我在 RecyclerView 中使用 SimpleExoPlayer,有时调用时会出错

simplePlayer.setPlayWhenReady(true);

视频播放器保持空白,出现问题的时刻并不总是相同(我没有找到确切的模拟方法)

例外:

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)

我的代码在自定义视图中运行(在回收器视图适配器中更新):

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);

            }
        }); 

我在从窗口分离时释放播放器(当回收器视图在我的自定义视图上调用 onDetachedFromWindow() 时):

if (player != null) {
        videoPlay.setVisibility(View.VISIBLE);
        postImage.setVisibility(View.VISIBLE);
        player.release();
        player = null;
}

有没有办法避免这个问题或在播放器启动时重试?

【问题讨论】:

    标签: java android exoplayer


    【解决方案1】:

    当我尝试使用 ..exoplayer2.ui.PlayerView 类时,我遇到了同样的问题。 ..exoplayer2.ui.PlayerControlView 没有问题。 这是我的代码:

     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);
    }
    

    我调用setup()函数一次,每次我想更改源时调用setSource()函数。

    当我想关闭音乐时,我调用player.release(); 并在释放setSource() 后,在player.prepare(videoSource); 行上给出同样的错误。

    我能够通过在每次源更改时创建新的 SimpleExoPlayer 来解决此问题。 代码如下:

     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);
    }
    

    我不知道这个解决方案的优化程度,但总比不发布播放器要好。

    【讨论】:

    • 为 recylerview 的每个项目重新创建 ExoPlayer 的实例对我有用。
    猜你喜欢
    • 2013-06-18
    • 2013-12-02
    • 1970-01-01
    • 2016-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-08
    • 2023-04-02
    相关资源
    最近更新 更多