簡體   English   中英

Android - VideoView,在播放視頻時獲取當前位置?

[英]Android - VideoView, getting current position as video is playing?

我有一個從內部存儲器播放的 VideoView。 當我的視頻正在播放 VideoView 日志MediaPlayer: error (1, -1004) 我有一個 onErrorListener 附加到 VideoView 我想從那里管理這個錯誤。 我的目標是獲得最后一個位置(來自getCurrentPosition() )並使用seekTo(int position)從該位置再次啟動我的播放器。 我的視頻文件有效(通過在其他播放器上播放驗證)。 我現在的問題是從 VideoView 獲取最后一個有效位置。 當我執行mp.getCurrentPosition / mVideoView.getCurrentPosition()時,從 onError(MediaPlayer mp, int what, int extra) 調用getCurrentPosition()返回 0(非常正確)。 如何在播放時跟蹤播放器的當前位置?

這是我的代碼:

mVideoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
            @Override
            public boolean onError(MediaPlayer mp, int what, int extra) {
                switch (what) {
                    case MediaPlayer.MEDIA_ERROR_UNKNOWN:
                        Log.v("error", "media error unknown");
                        mediaErrorExtra(mp, extra, path);
                        break;
                    case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
                        Log.v("error", "media error server died");
                        mediaErrorExtra(mp, extra, path);
                        break;
                }
                return true;
            }
        });

private void mediaErrorExtra(MediaPlayer mp, int extra, String path){
        switch(extra){
            case MediaPlayer.MEDIA_ERROR_IO:

                if(!mp.isPlaying()){
                    Integer currentposition = mVideoView.getCurrentPosition();
                    if(currentposition != null){
                        Log.v("currentpos",Integer.toString(currentposition));
                    }
                    mVideoView.setVideoPath(path);
                    mVideoView.start();
                    //mVideoView.seekTo(currentposition);
                }
                break;
            case MediaPlayer.MEDIA_ERROR_MALFORMED:
                Log.v("error extra","media error malformed");
                break;
            case MediaPlayer.MEDIA_ERROR_UNSUPPORTED:
                Log.v("error extra","media error unsupported");
                break;
            case MediaPlayer.MEDIA_ERROR_TIMED_OUT:
                Log.v("error extra","media error timed out");
                break;
        }
    }

或者,是否有任何偵聽器在播放時提供播放器的當前位置? 我可以使用while(isPlaying()){int currentposition = mVideoView.getCurrrentPosition()}但我認為這是一種糟糕的處理方式。 任何建議將不勝感激。 提前致謝。

我展示了我使用的處理程序......

        private double currentTime = 0;
    private Handler mHandler = new Handler();

    //update Seekbar on UI thread
    public void updateProgressBar() {
        if (mHandler != null) {
            mHandler.postDelayedUpdateProgress 100);
        }
    }

 private Runnable UpdateProgress = new Runnable() {
      public void run() {
         currentTime = mediaPlayer.getCurrentPosition();
         txt.setText(String.format("%d min, %d sec",
         TimeUnit.MILLISECONDS.toMinutes((long) startTime),
         TimeUnit.MILLISECONDS.toSeconds((long) startTime) -
         TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.
         toMinutes((long) startTime)))
         );
         seekbar.setProgress((int)startTime);
         myHandler.postDelayed(this, 100);
      }
   };

你應該使用處理程序..

回答我的問題:

ScheduledExecutorService幫助解決了這個問題:

以下是我在播放器播放時獲取當前位置的方法:

    ScheduledExecutorService mScheduledExecutorService;
    int mCurrentposition = 0;
    Runnable UpdateCurrentPosition = new Runnable(){

        @Override
        public void run() {
            mCurrentposition = mVideoView.getCurrentPosition();
        }
    };

    @Override
    protected void onCreate(){
        ...
        mScheduledExecutorService = new ScheduledExecutor(1);

        mScheduledExecutorService.scheduleWithFixedDelay(new Runnable(){
            @Override
            public void run() {
                mVideoView.post(UpdateCurrentPosition);
            }
        },3000,1000,TimeUnit.MILLISECONDS);
    }

您對while的處理是正確的,但它需要更多的改進,因為 while 可能會完全阻塞 UI。

所以你應該做的是使用一個Handler ,它會每 1 秒觸發一次MediaPlayer位置的檢查,我認為,1 秒是非常合理的。

我已經使用這種方法為 MediaPlayer 實現了一個自定義的SeekBar ,它工作得很好。

private int time = 0;

private ScheduledExecutorService mScheduledExecutorService;
Runnable getPositionVideo = () -> {
    time = binding.videoView.getCurrentPosition();

};


   binding.videoView.setOnPreparedListener(mediaPlayer -> {
        binding.videoView.seekTo(position);
        binding.videoView.start();
        mScheduledExecutorService = new ScheduledThreadPoolExecutor(1);
        mScheduledExecutorService.scheduleWithFixedDelay(() -> {
            runOnUiThread(getPositionVideo);
            MediaControllerExitFullScreen.init(video_url, time);
        }, 1000, 1000, TimeUnit.MILLISECONDS);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM