检测 VideoVIew 是否正在缓冲

发布于 2024-12-11 14:27:16 字数 728 浏览 1 评论 0原文

有谁知道是否可以检测 VideoView 何时缓冲?

我想在视频缓冲时显示 ProgressDialog。

到目前为止,我尝试使用 OnPreparedListener,但这仅在视频首次加载时有效。如果视频正在播放并且用户将滑动条移动到不同的点,则视频即使正在缓冲,仍然处于“准备就绪”状态。

我还尝试了(我知道这很糟糕)一个只忙于等待 isPlaying() 的 AsyncThread:

private class BufferTask extends AsyncTask<Void, Void, Void> {

  protected Void doInBackground(Void...voids) {
    final VideoView videoView = (VideoView)findViewById(R.id.video);
    while (!videoView.isPlaying()) { }
    return null;
  }

 protected void onPostExecute(Void v) {
     // Hide the dialog here...
 }
}

这不起作用,因为一旦您调用 start(),VideoView 似乎就会被视为正在播放,即使它正在缓冲。

我能想到的唯一解决方案是构建一个自定义 VideoView 类型类,以便我可以访问其 MediaPlayer 实例。

有什么想法吗?感谢您的阅读。

Does anyone know if it's possible to detect when a VideoView is buffering?

I want to show a ProgressDialog when the video is buffering.

So far I tried using a OnPreparedListener, but that only works when the video is first loaded. If a video is playing and the user moves the scrub bar to a different point the video is still "prepared" even though it is buffering.

I also tried (I know this is awful) an AsyncThread that just busy waits on isPlaying():

private class BufferTask extends AsyncTask<Void, Void, Void> {

  protected Void doInBackground(Void...voids) {
    final VideoView videoView = (VideoView)findViewById(R.id.video);
    while (!videoView.isPlaying()) { }
    return null;
  }

 protected void onPostExecute(Void v) {
     // Hide the dialog here...
 }
}

This doesn't work because as soon as you call start() a VideoView seems to be considered playing even though it is buffering.

The only solution I can think of is building a custom VideoView type class so I can access its MediaPlayer instance.

Any ideas? Thanks for reading.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

过气美图社 2024-12-18 14:27:17

VideoView 在缓冲时显示进度。
下面的代码对我有用:

videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(final MediaPlayer mp) {
                mp.start();
                mp.setOnInfoListener(new MediaPlayer.OnInfoListener() {
                    @Override
                    public boolean onInfo(MediaPlayer mp, int what, int extra) {
                        switch (what) {
                            case MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START: {
                                progressBar.setVisibility(View.GONE);
                                return true;
                            }
                            case MediaPlayer.MEDIA_INFO_BUFFERING_START: {
                                progressBar.setVisibility(View.VISIBLE);
                                return true;
                            }
                            case MediaPlayer.MEDIA_INFO_BUFFERING_END: {
                                progressBar.setVisibility(View.GONE);
                                return true;
                            }
                        }
                        return false;
                    }
                });
            }
        });

VideoView showing Progress while Buffering.
Below code worked for me:

videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(final MediaPlayer mp) {
                mp.start();
                mp.setOnInfoListener(new MediaPlayer.OnInfoListener() {
                    @Override
                    public boolean onInfo(MediaPlayer mp, int what, int extra) {
                        switch (what) {
                            case MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START: {
                                progressBar.setVisibility(View.GONE);
                                return true;
                            }
                            case MediaPlayer.MEDIA_INFO_BUFFERING_START: {
                                progressBar.setVisibility(View.VISIBLE);
                                return true;
                            }
                            case MediaPlayer.MEDIA_INFO_BUFFERING_END: {
                                progressBar.setVisibility(View.GONE);
                                return true;
                            }
                        }
                        return false;
                    }
                });
            }
        });
冷心人i 2024-12-18 14:27:17

我正在研究类似的事情,但无法想出一个很好的解决方案。 此处发布了一些有趣的解决方案,您应该检查一下是否你还没见过他们。

不管怎样,我想出了以下在上面的线程中暗示的黑客方法,目前工作正常。

@Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
    float temp = ((float)mp.getCurrentPosition() / (float)mp.getDuration())*100;
    if(Math.abs(percent - temp) < 1) {
        buffer_fail++;
        if(buffer_fail == 15) {
            //buffer failed
        }
    }
}

I'm working on something similar, and couldn't come up with a great solution. Some interesting solutions were posted here that you should check out if you haven't seen them.

Anyway, I came up with the following hack that was hinted at in the above thread and works ok for now.

@Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
    float temp = ((float)mp.getCurrentPosition() / (float)mp.getDuration())*100;
    if(Math.abs(percent - temp) < 1) {
        buffer_fail++;
        if(buffer_fail == 15) {
            //buffer failed
        }
    }
}
情释 2024-12-18 14:27:17

这对我有用

boolean b_start = true;
boolean b_end = true;                                                                  
 final MediaPlayer.OnInfoListener onInfoToPlayStateListener = new MediaPlayer.OnInfoListener() {

        @Override
        public boolean onInfo(MediaPlayer mp, int what, int extra) {
            switch (what) {
                case MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START: {
                    dialog1.setVisibility(View.GONE);
                    b_end = false;
                    b_start = false;

                }
                case MediaPlayer.MEDIA_INFO_BUFFERING_START: {
                    if (b_start){
                    dialog1.setVisibility(View.VISIBLE);
                    }
                    b_start = true;

                }
                case MediaPlayer.MEDIA_INFO_BUFFERING_END: {
                    if(b_end){
                    dialog1.setVisibility(View.VISIBLE);
                    }
                    b_end = true;
                }
            }
            return false;
        }

    };


    videoView.setOnInfoListener(onInfoToPlayStateListener);

This worked for me

boolean b_start = true;
boolean b_end = true;                                                                  
 final MediaPlayer.OnInfoListener onInfoToPlayStateListener = new MediaPlayer.OnInfoListener() {

        @Override
        public boolean onInfo(MediaPlayer mp, int what, int extra) {
            switch (what) {
                case MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START: {
                    dialog1.setVisibility(View.GONE);
                    b_end = false;
                    b_start = false;

                }
                case MediaPlayer.MEDIA_INFO_BUFFERING_START: {
                    if (b_start){
                    dialog1.setVisibility(View.VISIBLE);
                    }
                    b_start = true;

                }
                case MediaPlayer.MEDIA_INFO_BUFFERING_END: {
                    if(b_end){
                    dialog1.setVisibility(View.VISIBLE);
                    }
                    b_end = true;
                }
            }
            return false;
        }

    };


    videoView.setOnInfoListener(onInfoToPlayStateListener);
迷雾森÷林ヴ 2024-12-18 14:27:16

API 级别 17,您现在可以从 MediaPlayer 访问 InfoListener:

final MediaPlayer.OnInfoListener onInfoToPlayStateListener = new MediaPlayer.OnInfoListener() {

    @Override
    public boolean onInfo(MediaPlayer mp, int what, int extra) {
        switch (what) {
            case MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START: {
                mProgressBar.setVisibility(View.GONE);
                return true;
            }
            case MediaPlayer.MEDIA_INFO_BUFFERING_START: {
                mProgressBar.setVisibility(View.VISIBLE);
                return true;
            }
            case MediaPlayer.MEDIA_INFO_BUFFERING_END: {
                mProgressBar.setVisibility(View.GONE);
                return true;
            }
        }
        return false;
    }

});

mVideoView.setOnInfoListener(onInfoToPlayStateListener);

Since API level 17, you can now access the InfoListener from the MediaPlayer:

final MediaPlayer.OnInfoListener onInfoToPlayStateListener = new MediaPlayer.OnInfoListener() {

    @Override
    public boolean onInfo(MediaPlayer mp, int what, int extra) {
        switch (what) {
            case MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START: {
                mProgressBar.setVisibility(View.GONE);
                return true;
            }
            case MediaPlayer.MEDIA_INFO_BUFFERING_START: {
                mProgressBar.setVisibility(View.VISIBLE);
                return true;
            }
            case MediaPlayer.MEDIA_INFO_BUFFERING_END: {
                mProgressBar.setVisibility(View.GONE);
                return true;
            }
        }
        return false;
    }

});

mVideoView.setOnInfoListener(onInfoToPlayStateListener);
沩ん囻菔务 2024-12-18 14:27:16

为了不实现自定义 VideoView,我使用了以下 hack。这个想法是每 1 秒检查一次当前位置是否与前 1 秒相同。如果是,则视频正在缓冲。如果没有,则视频确实正在播放。

final Handler handler = new Handler(); 
Runnable runnable = new Runnable() { 
    public void run() {
        int duration = videoView.getCurrentPosition();
        if (old_duration == duration && videoView.isPlaying()) {
            videoMessage.setVisibility(View.VISIBLE);
        } else {
            videoMessage.setVisibility(View.GONE);
        }
        old_duration = duration;

        handler.postDelayed(runnable, 1000);
    }
};
handler.postDelayed(runnable, 0);

videoMessage 只是一个 TextView,文本“Buffering...”放置在我的 VideoView 的中心。

I came with the following hack in order to not implement a custom VideoView. The idea is to check every 1 second if the current position is the same as 1 second before. If it is, the video is buffering. If not, the video is really playing.

final Handler handler = new Handler(); 
Runnable runnable = new Runnable() { 
    public void run() {
        int duration = videoView.getCurrentPosition();
        if (old_duration == duration && videoView.isPlaying()) {
            videoMessage.setVisibility(View.VISIBLE);
        } else {
            videoMessage.setVisibility(View.GONE);
        }
        old_duration = duration;

        handler.postDelayed(runnable, 1000);
    }
};
handler.postDelayed(runnable, 0);

videoMessage is just a TextView with the text "Buffering..." placed in the center of my VideoView.

窗影残 2024-12-18 14:27:16

每次 VideoView 缓冲时,以下代码都会显示一个缓冲对话框。

    final ProgressDialog bufferingDialog;
    bufferingDialog = ProgressDialog.show(context,
            "Buffering", "Please wait", true, true);

    VideoView videoView;
    videoView = (VideoView) findViewById(R.id.video_view);
    videoView.setVideoPath(path);
    videoView.setMediaController(new MediaController(context));
    videoView.requestFocus();
    videoView.start();
    videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
        @Override
        public void onPrepared(MediaPlayer mp) {
            mp.setOnInfoListener(new MediaPlayer.OnInfoListener() {
                @Override
                public boolean onInfo(MediaPlayer mp, int what, int extra) {
                    if (what == MediaPlayer.MEDIA_INFO_BUFFERING_START)
                        bufferingDialog.show();
                    if (what == MediaPlayer.MEDIA_INFO_BUFFERING_END)
                        bufferingDialog.dismiss();
                    return false;
                }
            });
        }
    });
    videoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
        @Override
        public boolean onError(MediaPlayer mp, int what, int extra) {
            bufferingDialog.dismiss();
            return false;
        }
    });

Following code will show a buffering dialog every time the VideoView is buffering.

    final ProgressDialog bufferingDialog;
    bufferingDialog = ProgressDialog.show(context,
            "Buffering", "Please wait", true, true);

    VideoView videoView;
    videoView = (VideoView) findViewById(R.id.video_view);
    videoView.setVideoPath(path);
    videoView.setMediaController(new MediaController(context));
    videoView.requestFocus();
    videoView.start();
    videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
        @Override
        public void onPrepared(MediaPlayer mp) {
            mp.setOnInfoListener(new MediaPlayer.OnInfoListener() {
                @Override
                public boolean onInfo(MediaPlayer mp, int what, int extra) {
                    if (what == MediaPlayer.MEDIA_INFO_BUFFERING_START)
                        bufferingDialog.show();
                    if (what == MediaPlayer.MEDIA_INFO_BUFFERING_END)
                        bufferingDialog.dismiss();
                    return false;
                }
            });
        }
    });
    videoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
        @Override
        public boolean onError(MediaPlayer mp, int what, int extra) {
            bufferingDialog.dismiss();
            return false;
        }
    });
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文