android开发视频播放相关使用

由于工作中经常用到视频多媒体相关系列操作,在此总结一下这个视频播放的使用,本例使用系统自带VideoView和SurfaceView两种使用方法进行视频播放,VideoView对视频进行播放实际上内部还是用过SurfaceView和MediaPlayer来实现的,是android已经包装好可以直接使用的视频播放View而已。

这边只记录主要的和需要注意的事项:
android开发视频播放相关使用_第1张图片

android开发视频播放相关使用_第2张图片

SurfaceView方式关键代码:

public class SurfaceViewActivity extends Activity {
    private EditText nameText;
    private String path;
    // MediaPlayer实际上主要用于音频输出,SurfaceView主要作用于显示MediaPlayer输出的界面
    private MediaPlayer mediaPlayer;
    private SurfaceView surfaceView;
    private boolean pause;
    private int position;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.surfaceview);

        mediaPlayer = new MediaPlayer();
        nameText = (EditText) this.findViewById(R.id.filename);
        surfaceView = (SurfaceView) this.findViewById(R.id.surfaceView);
        // 把输送给surfaceView的视频画面,直接显示到屏幕上,不要维持它自身的缓冲区
        surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        surfaceView.getHolder().setFixedSize(176, 144);
        surfaceView.getHolder().setKeepScreenOn(true);// 设置播放时打开屏幕
        surfaceView.getHolder().addCallback(new SurfaceCallback());


    }

    private final class SurfaceCallback implements Callback {
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        }

        public void surfaceCreated(SurfaceHolder holder) {
            if (position > 0 && path != null) {
                play(position);
                position = 0;
            }
        }

        public void surfaceDestroyed(SurfaceHolder holder) {
            if (mediaPlayer.isPlaying()) {
                position = mediaPlayer.getCurrentPosition();
                mediaPlayer.stop();
            }
        }
    }

    @Override
    protected void onDestroy() {
        mediaPlayer.release();
        mediaPlayer = null;
        super.onDestroy();
    }

    public void mediaplay(View v) {
        switch (v.getId()) {
        case R.id.playbutton:
            String filename = nameText.getText().toString();
            if (filename.startsWith("http")) {
                // path = filename;
                path = "http://baishi.baidu.com/watch/07744898579139394846.html?page=videoMultiNeed";
                play(0);
            } else {
                File file = new File(Environment.getExternalStorageDirectory(), filename);
                if (file.exists()) {
                    // path = file.getAbsolutePath();
                    path = "/mnt/sdcard/X1_Video/泊车辅助.mp4";
                    play(0);
                } else {
                    path = null;
                    Toast.makeText(this, R.string.filenoexsit, 1).show();
                }
            }

            break;

        case R.id.pausebutton:
            if (mediaPlayer.isPlaying()) {
                mediaPlayer.pause();
                pause = true;
            } else {
                if (pause) {
                    mediaPlayer.start();
                    pause = false;
                }
            }
            break;

        case R.id.resetbutton:
            if (mediaPlayer.isPlaying()) {
                mediaPlayer.seekTo(0);
            } else {
                if (path != null) {
                    play(0);
                }
            }
            break;
        case R.id.stopbutton:
            if (mediaPlayer.isPlaying()) {
                mediaPlayer.stop();
            }
            break;
        }
    }

    private void play(int position) {
        try {
            mediaPlayer.reset();
            // 设置资源路径
            mediaPlayer.setDataSource(path);
//          mediaPlayer.setDataSource(MainActivity.this,  Uri.parse("/mnt/sdcard/X1_Video/泊车辅助.mp4"));
            // 设置播放时的图像输出用surfaceView来显示
            mediaPlayer.setDisplay(surfaceView.getHolder());
            mediaPlayer.prepare();// 缓冲
            // mediaPlayer.prepareAsync();
            mediaPlayer.setOnPreparedListener(new PrepareListener(position));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private final class PrepareListener implements OnPreparedListener {
        private int position;

        public PrepareListener(int position) {
            this.position = position;
        }

        public void onPrepared(MediaPlayer mp) {
            mediaPlayer.start();// 播放视频
            if (position > 0)
                mediaPlayer.seekTo(position);
        }
    }
}

注意事项:MediaPlayer实际上主要用于音频输出,SurfaceView主要作用于显示MediaPlayer输出的界面。

VideoView方式关键代码:

public class VideoActivity extends Activity implements OnClickListener {
    private final String SDCARD_PATH = Environment.getExternalStorageDirectory().getAbsolutePath() + "/X1_Video";// /mnt/sdcard
    private ImageView mBack, mHome, mPlay, mPause;
    private MyVideoView mVideoView = null;
    private MediaController mMediaController = null;

    private TextView mFileName, mCurrTime, mTotalTime;
    private SeekBar mVideoSeekBar;
    private int mDuration, mCurrPosi;
    private boolean isCompletion = false;
    /**
     * 作用 update SeekbarView 和 update time、
     */
    private Handler mTimerHandler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            mCurrPosi = mVideoView.getCurrentPosition();
            mCurrTime.setText(stringForTime(mCurrPosi));
            mVideoSeekBar.setProgress((mCurrPosi * mVideoSeekBar.getMax()) / mDuration);

            if (!isCompletion) {// 正在播放,还没播放完
                mTimerHandler.sendEmptyMessageDelayed(0, 1000);
            } else {// 播放完时
                mPlay.setVisibility(View.VISIBLE);
                mPause.setVisibility(View.GONE);
                mVideoSeekBar.setProgress(0);
                mCurrTime.setText("00:00");
            }

        };
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_play_video);

        String fileName = getIntent().getStringExtra("file_name");
        final String filePath = SDCARD_PATH + File.separator + fileName + ".mp4";

        mBack = (ImageView) findViewById(R.id.im_back_to_activity);
        mBack.setOnClickListener(VideoActivity.this);
        mHome = (ImageView) findViewById(R.id.im_back_to_home);
        mHome.setOnClickListener(VideoActivity.this);

        mPlay = (ImageView) findViewById(R.id.im_play_icon);
        mPlay.setOnClickListener(VideoActivity.this);
        mPause = (ImageView) findViewById(R.id.im_pause_icon);
        mPause.setOnClickListener(VideoActivity.this);

        mFileName = (TextView) findViewById(R.id.tv_play_view_headtext);
        mFileName.setText(fileName);

        mCurrTime = (TextView) findViewById(R.id.tv_play_schedule_head);
        mTotalTime = (TextView) findViewById(R.id.tv_play_schedule_end);

        mVideoView = (MyVideoView) findViewById(R.id.videoview);
        mMediaController = new MediaController(this);
        // mVideoView.setMediaController(mMediaController);
        // 显示控制栏
        mMediaController.setPrevNextListeners(new OnClickListener() {

            @Override
            /**
             * 下一曲
             */
            public void onClick(View v) {

            }
        }, new OnClickListener() {

            @Override
            /**
             * 上一曲
             */
            public void onClick(View v) {

            }
        });
        mMediaController.hide();

        // mVideoView.setVideoPath(filePath);
        mVideoView.setVideoURI(android.net.Uri.parse(filePath));
        // mVideoView.setVideoURI(Uri.parse("http://10.0.2.2:8080/X1_Video/res/movie/泊车辅助.mp4"));
        mVideoView.requestFocus();// 请求音频聚焦

        try {
            mCurrPosi = mVideoView.getCurrentPosition();
            mCurrTime.setText(stringForTime(mCurrPosi));

            MediaPlayer mediaPlayer = new MediaPlayer();
            mediaPlayer.setDataSource(filePath);
            mediaPlayer.prepare();
            mDuration = mediaPlayer.getDuration();
            mTotalTime.setText(stringForTime(mDuration));

        } catch (IllegalArgumentException | SecurityException | IllegalStateException | IOException e) {
            e.printStackTrace();
        }

        mVideoSeekBar = (SeekBar) findViewById(R.id.sb_play_seekbar);
        mVideoSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
            private int mProgress;

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                mVideoView.seekTo(mProgress * (mDuration / seekBar.getMax()));
                mTimerHandler.sendEmptyMessageDelayed(0, 1000);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                mTimerHandler.removeMessages(0);
                isCompletion = false;
            }

            @Override
            /**
             * 最大进度值100
             */
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                mProgress = progress;
            }
        });

        mVideoView.setOnCompletionListener(new OnCompletionListener() {

            @Override
            /**
             * 播放完成时回调
             */
            public void onCompletion(MediaPlayer mp) {
                isCompletion = true;
                // mTimerHandler.removeMessages(0);若是此处采用remove,
                // mCurrTime进度会比总时长少一秒
            }
        });

        mVideoView.setOnPreparedListener(new OnPreparedListener() {

            @Override
            public void onPrepared(MediaPlayer mp) {
                if (null != mVideoView)
                    mVideoView.start();
            }
        });

        mTimerHandler.sendEmptyMessageDelayed(0, 1000);
    }

    // 将长度positon转换为时间
    private String stringForTime(int timeMs) {
        int totalSeconds = timeMs / 1000;

        int seconds = totalSeconds % 60;
        int minutes = (totalSeconds / 60) % 60;
        int hours = totalSeconds / 3600;

        StringBuilder mFormatBuilder = new StringBuilder();
        mFormatBuilder.setLength(0);

        Formatter mFormatter = new Formatter(mFormatBuilder, Locale.getDefault());
        if (hours > 0) {
            return mFormatter.format("%d:%02d:%02d", hours, minutes, seconds).toString();
        } else {
            return mFormatter.format("%02d:%02d", minutes, seconds).toString();
        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.im_back_to_activity:
        case R.id.im_back_to_home:
            VideoActivity.this.finish();
            break;
        case R.id.im_play_icon:
            if (mVideoView != null) {
                mVideoView.start();
                mTimerHandler.sendEmptyMessageDelayed(0, 1000);
                mPlay.setVisibility(View.GONE);
                mPause.setVisibility(View.VISIBLE);
                isCompletion = false;
            }
            break;
        case R.id.im_pause_icon:
            if (mVideoView.isPlaying()) {
                mVideoView.pause();
                mTimerHandler.removeMessages(0);
                mPlay.setVisibility(View.VISIBLE);
                mPause.setVisibility(View.GONE);
            }
            break;
        default:
            break;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mVideoView.isPlaying()) {
            mVideoView.stopPlayback();
            mTimerHandler.removeMessages(0);
        }
        // 显示底部导航栏
        Intent hide = new Intent();
        hide.setAction("com.asir.appwidget.provider.show");
        hide.putExtra("current_app_id", -1);
        sendBroadcast(hide);
    }
}

再使用中可能要获取视频文件当前播放时间视频总时长,首先官方并没有提供获取当前播放时间的方法,只有个getCurrentPosition()方法,可以获取当前播放的进度。代码如下:

mVideoView.getCurrentPosition()

我们可以根据播放进度来获取当前播放时间,转化方法如下:

/**
     *  将进度positon转换为时间
     * @param position
     * @return
     */
    private String getTimebyCurrentPosition(int position) {
        int totalSeconds =  position / 1000;

        int seconds = totalSeconds % 60;
        int minutes = (totalSeconds / 60) % 60;
        int hours = totalSeconds / 3600;

        StringBuilder mFormatBuilder = new StringBuilder();
        mFormatBuilder.setLength(0);

        Formatter mFormatter = new Formatter(mFormatBuilder, Locale.getDefault());
        if (hours > 0) {
            return mFormatter.format("%d:%02d:%02d", hours, minutes, seconds).toString();
        } else {
            return mFormatter.format("%02d:%02d", minutes, seconds).toString();
        }
    }

至于获取总时长VideoView提供一个getDuration()方法,实际上内部也是使用了mediaPlayer.getDuration(),但是此方法一直都是返回-1,我们这边用另外一种方法来获取,代码如下:

MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(filePath);
mediaPlayer.prepare();
mDuration = mediaPlayer.getDuration();

另外VideoView一般跟自带的控制菜单MediaController一起使用,具体使用方式如下:

mMediaController = new MediaController(this);
        mVideoView.setMediaController(mMediaController);
        // 显示控制栏
        mMediaController.setPrevNextListeners(new OnClickListener() {

            @Override
            /**
             * 下一曲
             */
            public void onClick(View v) {

            }
        }, new OnClickListener() {

            @Override
            /**
             * 上一曲
             */
            public void onClick(View v) {

            }
        });
        mMediaController.hide();

不管是使用哪种方式,都要请求音频聚焦,这里涉及到车载导航系统中一个切源的概念。

最后就是若要播放网络视频,只需要将设置的路劲path换用成设置URI方式即可,具体代码如下:

// 播放本地视频
// mVideoView.setVideoPath(filePath);
mVideoView.setVideoURI(android.net.Uri.parse(filePath));
// 播放网络视频
// mVideoView.setVideoURI(Uri.parse("http://10.0.2.2:8080/X1_Video/res/movie/泊车辅助.mp4"));

实际上内部还是使用了mediaPlayer,如下:

// 设置资源路径
            mediaPlayer.setDataSource(path);
//          mediaPlayer.setDataSource(MainActivity.this,  Uri.parse("/mnt/sdcard/X1_Video/泊车辅助.mp4"));

源码点击下载

你可能感兴趣的:(Android多媒体应用)