赞
踩
Android提供了常见的视频的编码、解码机制。使用Android自带的MediaPlayer、MediaController等类可以很方便的实现视频播放的功能。支持的视频格式有MP4和3GP等。这些多媒体数据可以来自于Android应用的资源文件,也可以来自于外部存储器上的文件,甚至可以是来自于网络上的文件流。
下面来说一下视频播放的几种实现方式:
这种方式是最简单的实现方式。VideoView继承了SurfaceView同时实现了MediaPlayerControl接口,MediaController则是安卓封装的辅助控制器,带有暂停,播放,停止,进度条等控件。通过VideoView+MediaController可以很轻松的实现视频播放、停止、快进、快退等功能。
布局文件如下:
- <?xml version="1.0" encoding="utf-8"?>
- <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:context=".VideoViewTestActivity">
- <VideoView
- android:id="@+id/videoView"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
- </android.support.constraint.ConstraintLayout>
程序代码如下:
- public class VideoViewTestActivity extends AppCompatActivity {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_video_view_test);
- VideoView videoView = (VideoView)findViewById(R.id.videoView);
-
- //加载指定的视频文件
- String path = Environment.getExternalStorageDirectory().getPath()+"/20180730.mp4";
- videoView.setVideoPath(path);
-
- //创建MediaController对象
- MediaController mediaController = new MediaController(this);
-
- //VideoView与MediaController建立关联
- videoView.setMediaController(mediaController);
-
- //让VideoView获取焦点
- videoView.requestFocus();
-
- }
- }

使用此实现方式的步骤:
实现效果图如下:
界面中的快退、播放、快进、时间、进度条等是由MediaController提供的。
虽然VideoView的实现方式很简单,但是由于是自带的封装好的类,所以无论是播放器的大小、位置以及控制都不受我们控制。
这种实现方式步骤如下:
在实现第二步之前需要先给surfaceHolder设置一个callback,callback的3个回调函数如下:
- @Override
- public void surfaceCreated(SurfaceHolder holder) {
- }
-
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
-
- }
-
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {
-
- }
布局文件如下:
- <?xml version="1.0" encoding="utf-8"?>
- <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:context=".PlayVideoActivity">
-
- <RelativeLayout
- android:id="@+id/root_rl"
- android:layout_width="match_parent"
- android:layout_height="400dp"
- android:background="#000000">
-
- <SurfaceView
- android:id="@+id/surfaceView"
- android:layout_width="match_parent"
- android:layout_height="400dp" />
- <ImageView
- android:id="@+id/playOrPause"
- android:layout_width="60dp"
- android:layout_height="60dp"
- android:layout_centerInParent="true"
- android:src="@android:drawable/ic_media_play"/>
- <LinearLayout
- android:id="@+id/control_ll"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:background="#005500"
- android:orientation="vertical">
-
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="10dp"
- android:layout_marginRight="10dp"
- android:orientation="horizontal"
- android:paddingBottom="5dp">
-
- <TextView
- android:id="@+id/tv_start_time"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_marginLeft="30dp"
- android:text="00.00"
- android:textColor="#ffffff"/>
- <TextView
- android:id="@+id/tv_separate_time"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_toRightOf="@+id/tv_start_time"
- android:layout_marginLeft="1dp"
- android:text="/"
- android:textColor="#ffffff"/>
- <TextView
- android:id="@+id/tv_end_time"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_toRightOf="@+id/tv_separate_time"
- android:layout_marginLeft="1dp"
- android:text="00.00"
- android:textColor="#ffffff"/>
- <ImageView
- android:id="@+id/tv_backward"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@+id/tv_start_time"
- android:layout_alignParentLeft="true"
- android:layout_marginLeft="1dp"
- android:src="@android:drawable/ic_media_rew"/>
-
- <SeekBar
- android:id="@+id/tv_progess"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_toRightOf="@+id/tv_backward"
- android:layout_toLeftOf="@+id/tv_forward"
- android:layout_below="@+id/tv_start_time"/>
-
- <ImageView
- android:id="@+id/tv_forward"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@+id/tv_start_time"
- android:layout_alignParentRight="true"
- android:layout_marginRight="1dp"
- android:src="@android:drawable/ic_media_ff"/>
-
- </RelativeLayout>
-
- </LinearLayout>
- </RelativeLayout>
-
- </android.support.constraint.ConstraintLayout>

程序代码如下:
- public class PlayVideoActivity extends AppCompatActivity implements SurfaceHolder.Callback,
- MediaPlayer.OnPreparedListener,
- MediaPlayer.OnCompletionListener,
- MediaPlayer.OnErrorListener,
- MediaPlayer.OnInfoListener, View.OnClickListener,
- MediaPlayer.OnSeekCompleteListener,
- MediaPlayer.OnVideoSizeChangedListener,
- SeekBar.OnSeekBarChangeListener,
- {
-
- private ImageView playOrPauseIv;
- private SurfaceView videoSuf;
- private MediaPlayer mPlayer;
- private SeekBar mSeekBar;
- private String path;
- private RelativeLayout rootViewRl;
- private LinearLayout controlLl;
- private TextView startTime, endTime;
- private ImageView forwardButton, backwardButton;
- private boolean isShow = false;
-
- public static final int UPDATE_TIME = 0x0001;
- public static final int HIDE_CONTROL = 0x0002;
-
- private Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case UPDATE_TIME:
- updateTime();
- mHandler.sendEmptyMessageDelayed(UPDATE_TIME, 500);
- break;
- case HIDE_CONTROL:
- hideControl();
- break;
- }
- }
- };
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_play_video);
- initViews();
- initData();
- initSurfaceView();
- initPlayer();
- initEvent();
- }
- private void initData() {
- path = Environment.getExternalStorageDirectory().getPath() + "/20180730.mp4";//这里写上你的视频地址
- }
-
- private void initEvent() {
- playOrPauseIv.setOnClickListener(this);
- rootViewRl.setOnClickListener(this);
- rootViewRl.setOnTouchListener(this);
- forwardButton.setOnClickListener(this);
- backwardButton.setOnClickListener(this);
- mSeekBar.setOnSeekBarChangeListener(this);
- }
- private void initSurfaceView() {
- videoSuf = (SurfaceView) findViewById(R.id.surfaceView);
- videoSuf.setZOrderOnTop(false);
- videoSuf.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
- videoSuf.getHolder().addCallback(this);
- }
-
- private void initPlayer() {
- mPlayer = new MediaPlayer();
- mPlayer.setOnCompletionListener(this);
- mPlayer.setOnErrorListener(this);
- mPlayer.setOnInfoListener(this);
- mPlayer.setOnPreparedListener(this);
- mPlayer.setOnSeekCompleteListener(this);
- mPlayer.setOnVideoSizeChangedListener(this);
- try {
- //使用手机本地视频
- mPlayer.setDataSource(path);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- private void initViews() {
- playOrPauseIv = (ImageView) findViewById(R.id.playOrPause);
- startTime = (TextView) findViewById(R.id.tv_start_time);
- endTime = (TextView) findViewById(R.id.tv_end_time);
- mSeekBar = (SeekBar) findViewById(R.id.tv_progess);
- rootViewRl = (RelativeLayout) findViewById(R.id.root_rl);
- controlLl = (LinearLayout) findViewById(R.id.control_ll);
- forwardButton = (ImageView) findViewById(R.id.tv_forward);
- backwardButton = (ImageView) findViewById(R.id.tv_backward);
- }
-
- @Override
- public void surfaceCreated(SurfaceHolder holder) {
- mPlayer.setDisplay(holder);
- mPlayer.prepareAsync();
- }
-
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
-
- }
-
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {
-
- }
- @Override
- public void onPrepared(MediaPlayer mp) {
- startTime.setText(FormatTimeUtil.formatLongToTimeStr(mp.getCurrentPosition()));
- endTime.setText(FormatTimeUtil.formatLongToTimeStr(mp.getDuration()));
- mSeekBar.setMax(mp.getDuration());
- mSeekBar.setProgress(mp.getCurrentPosition());
- }
- @Override
- public void onCompletion(MediaPlayer mp) {
-
- }
- @Override
- public boolean onError(MediaPlayer mp, int what, int extra) {
- return false;
- }
-
- @Override
- public boolean onInfo(MediaPlayer mp, int what, int extra) {
- return false;
- }
- private void play() {
- if (mPlayer == null) {
- return;
- }
- Log.i("playPath", path);
- if (mPlayer.isPlaying()) {
- mPlayer.pause();
- mHandler.removeMessages(UPDATE_TIME);
- mHandler.removeMessages(HIDE_CONTROL);
- playOrPauseIv.setVisibility(View.VISIBLE);
- playOrPauseIv.setImageResource(android.R.drawable.ic_media_play);
- } else {
- mPlayer.start();
- mHandler.sendEmptyMessageDelayed(UPDATE_TIME, 500);
- mHandler.sendEmptyMessageDelayed(HIDE_CONTROL, 5000);
- playOrPauseIv.setVisibility(View.INVISIBLE);
- playOrPauseIv.setImageResource(android.R.drawable.ic_media_pause);
- }
- }
- @Override
- public void onSeekComplete(MediaPlayer mp) {
- //TODO
- }
-
- @Override
- public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
-
- }
- @Override
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.tv_backward:
- backWard();
- break;
- case R.id.tv_forward:
- forWard();
- break;
- case R.id.playOrPause:
- play();
- break;
- case R.id.root_rl:
- showControl();
- break;
- }
- }
- /**
- * 更新播放时间
- */
- private void updateTime() {
-
- startTime.setText(FormatTimeUtil.formatLongToTimeStr(
- mPlayer.getCurrentPosition()));
- mSeekBar.setProgress(mPlayer.getCurrentPosition());
- }
-
- /**
- * 隐藏进度条
- */
- private void hideControl() {
- isShow = false;
- mHandler.removeMessages(UPDATE_TIME);
- controlLl.animate().setDuration(300).translationY(controlLl.getHeight());
- }
- /**
- * 显示进度条
- */
- private void showControl() {
- if (isShow) {
- play();
- }
- isShow = true;
- mHandler.removeMessages(HIDE_CONTROL);
- mHandler.sendEmptyMessage(UPDATE_TIME);
- mHandler.sendEmptyMessageDelayed(HIDE_CONTROL, 5000);
- controlLl.animate().setDuration(300).translationY(0);
- }
- /**
- * 设置快进10秒方法
- */
- private void forWard(){
- if(mPlayer != null){
- int position = mPlayer.getCurrentPosition();
- mPlayer.seekTo(position + 10000);
- }
- }
-
- /**
- * 设置快退10秒的方法
- */
- public void backWard(){
- if(mPlayer != null){
- int position = mPlayer.getCurrentPosition();
- if(position > 10000){
- position-=10000;
- }else{
- position = 0;
- }
- mPlayer.seekTo(position);
- }
- }
-
- //OnSeekBarChangeListener
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress, boolean b) {
- if(mPlayer != null && b){
- mPlayer.seekTo(progress);
- }
- }
-
- @Override
- public void onStartTrackingTouch(SeekBar seekBar) {
- }
-
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {
-
- }
- }

注意事项:MediaPlayer有prepare和prepareAsync两种方法。这两种方法的区别是:prepare方法是将资源同步缓存到内存中,一般加载本地较小的资源可以用这个,如果是较大的资源或者网络资源建议使用prepareAsync方法,异步加载。
实现效果如下所示:
第二种实现方式使用的是自定义控件,MediaPlayer+SurfaceView也可以使用系统自带的MediaController控制器。
使用这个方式实现,布局文件只需一个SurfaceView即可,其他的控件都交给MediaController控制器,布局文件如下:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:context=".MediaControllerTestActivity"
- android:id="@+id/root_ll">
- <SurfaceView
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:id="@+id/controll_surfaceView"/>
- </LinearLayout>
程序代码如下:
- public class MediaControllerTestActivity extends Activity implements
- MediaController.MediaPlayerControl,
- MediaPlayer.OnBufferingUpdateListener,
- SurfaceHolder.Callback{
- private MediaPlayer mediaPlayer;
- private MediaController controller;
- private int bufferPercentage = 0;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_media_controller_test);
- mediaPlayer = new MediaPlayer();
- controller = new MediaController(this);
- controller.setAnchorView(findViewById(R.id.root_ll));
- initSurfaceView();
- }
-
- private void initSurfaceView() {
- SurfaceView videoSuf = (SurfaceView) findViewById(R.id.controll_surfaceView);
- videoSuf.setZOrderOnTop(false);
- videoSuf.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
- videoSuf.getHolder().addCallback(this);
- }
- @Override
- protected void onResume() {
- super.onResume();
- try {
- String path = Environment.getExternalStorageDirectory().getPath() + "/20180730.mp4";
- mediaPlayer.setDataSource(path);
- mediaPlayer.setOnBufferingUpdateListener(this);
- //mediaPlayer.prepare();
-
- controller.setMediaPlayer(this);
- controller.setEnabled(true);
-
- }catch (IOException e){
- e.printStackTrace();
- }
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- if (mediaPlayer.isPlaying()){
- mediaPlayer.stop();
- }
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- if (null != mediaPlayer){
- mediaPlayer.release();
- mediaPlayer = null;
- }
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- controller.show();
- return super.onTouchEvent(event);
- }
-
- //MediaPlayer
- @Override
- public void onPointerCaptureChanged(boolean hasCapture) {
-
- }
- //MediaPlayerControl
- @Override
- public void onBufferingUpdate(MediaPlayer mediaPlayer, int i) {
- bufferPercentage = i;
- }
-
- @Override
- public void start() {
- if (null != mediaPlayer){
- mediaPlayer.start();
- }
- }
-
- @Override
- public void pause() {
- if (null != mediaPlayer){
- mediaPlayer.pause();
- }
- }
-
- @Override
- public int getDuration() {
- return mediaPlayer.getDuration();
- }
-
- @Override
- public int getCurrentPosition() {
- return mediaPlayer.getCurrentPosition();
- }
-
- @Override
- public void seekTo(int i) {
- mediaPlayer.seekTo(i);
- }
-
- @Override
- public boolean isPlaying() {
- if (mediaPlayer.isPlaying()){
- return true;
- }
- return false;
- }
-
- @Override
- public int getBufferPercentage() {
- return bufferPercentage;
- }
-
- @Override
- public boolean canPause() {
- return true;
- }
-
- @Override
- public boolean canSeekBackward() {
- return true;
- }
-
- @Override
- public boolean canSeekForward() {
- return true;
- }
-
- @Override
- public int getAudioSessionId() {
- return 0;
- }
-
- //SurfaceHolder.callback
- @Override
- public void surfaceCreated(SurfaceHolder surfaceHolder) {
- mediaPlayer.setDisplay(surfaceHolder);
- mediaPlayer.prepareAsync();
- }
-
- @Override
- public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
-
- }
-
- @Override
- public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
-
- }
- }

效果图如下:
四、还可以使用ijk或者Vitamio
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。