Android实现视频播放的3种实现方式[通俗易懂]

您所在的位置:网站首页 点播怎么写 Android实现视频播放的3种实现方式[通俗易懂]

Android实现视频播放的3种实现方式[通俗易懂]

2024-04-23 04:31| 来源: 网络整理| 查看: 265

大家好,又见面了,我是你们的朋友全栈君。

Android提供了常见的视频的编码、解码机制。使用Android自带的MediaPlayer、MediaController等类可以很方便的实现视频播放的功能。支持的视频格式有MP4和3GP等。这些多媒体数据可以来自于Android应用的资源文件,也可以来自于外部存储器上的文件,甚至可以是来自于网络上的文件流。

下面来说一下视频播放的几种实现方式:

1、MediaController+VideoView实现方式

这种方式是最简单的实现方式。VideoView继承了SurfaceView同时实现了MediaPlayerControl接口,MediaController则是安卓封装的辅助控制器,带有暂停,播放,停止,进度条等控件。通过VideoView+MediaController可以很轻松的实现视频播放、停止、快进、快退等功能。

布局文件如下:

程序代码如下:

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

使用此实现方式的步骤:

加载指定的视频文件建立VideoView和MediaController之间的关联,这样就不需要自己去控制视频的播放、暂停等。让MediaController控制即可。VideoView获取焦点。

实现效果图如下:

Android实现视频播放的3种实现方式[通俗易懂]Android实现视频播放的3种实现方式[通俗易懂]

界面中的快退、播放、快进、时间、进度条等是由MediaController提供的。

2、MediaPlayer+SurfaceView+自定义控制器

虽然VideoView的实现方式很简单,但是由于是自带的封装好的类,所以无论是播放器的大小、位置以及控制都不受我们控制。

这种实现方式步骤如下:

创建MediaPlayer对象,并让它加载指定的视频文件。可以是应用的资源文件、本地文件路径、或者URL。在界面布局文件中定义SurfaceView组件,并为SurfaceView的SurfaceHolder添加Callback监听器。调用MediaPlayer对象的setDisplay(SurfaceHolder sh)将所播放的视频图像输出到指定的SurfaceView组件。调用MediaPlayer对象的prepareAsync()或prepare()方法装载流媒体文件调用MediaPlayer对象的start()、stop()和pause()方法来控制视频的播放。

在实现第二步之前需要先给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) { }

布局文件如下:

程序代码如下:

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方法,异步加载。

实现效果如下所示:

Android实现视频播放的3种实现方式[通俗易懂]Android实现视频播放的3种实现方式[通俗易懂]3、MediaPlayer+SurfaceView+MediaController

第二种实现方式使用的是自定义控件,MediaPlayer+SurfaceView也可以使用系统自带的MediaController控制器。

使用这个方式实现,布局文件只需一个SurfaceView即可,其他的控件都交给MediaController控制器,布局文件如下:

程序代码如下:

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

效果图如下:

Android实现视频播放的3种实现方式[通俗易懂]Android实现视频播放的3种实现方式[通俗易懂]

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/132910.html原文链接:https://javaforall.cn



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3