关于android的VideoView的使用
2013-11-04 15:27
477 查看
Android自带了一个VideoView,用来播放视频和网络视频,它是继承SurfaceView使用MediaPlayer来做播放的类。
VideoView使用的一个简单实例:
Layout文件:
播放代码:
注意要播放网络视频的话,还要在AndroidManifest.xml中加入:
权限
显示的图像:
由于是播放的视频,所以截不到图像,中间是一个控制条,通过
来加入,如果没有也可以播放,只是没有了这个控制条。这是android自带的控制条,具有暂停,快进,快退,一个进度显示条等。
完整工程代码可以到我的资源下载区下载。
http://download.csdn.net/detail/taoxugang2012/6500453
当然很多时候我们是不满足于使用别人的代码的,使用android的VideoView任然存在有些不足,比如说系统带的控制条太难看,全屏播放时无法全屏。
通过查看源码可以修改该VideoView类,最开始,将源代码拷贝过来用,会出现一些问题,修改了一些部分后就可用了,具体如下:
这个代码没有做功能性修改,只是做了简单移植,编译通过,能够正常播放。
要使用自己定义的videoview,还需要在自己的xml写上完整控件路径
<com.example.listview.VideoView
android:id="@+id/videowiew"
android:layout_gravity="center_horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
这个部分,还不算完美,我之后还想把android的控制条重写。
VideoView使用的一个简单实例:
Layout文件:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" android:background="@drawable/bg" > <Button android:id="@+id/btn" android:text="@string/playbtn" android:layout_width="fill_parent" android:layout_height="wrap_content"/> <VideoView android:id="@+id/videowiew" android:layout_gravity="center_horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent"/> </LinearLayout>
播放代码:
public class ListviewActivity extends Activity { VideoView mVideoView; Button btn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_listview); btn = (Button)findViewById(R.id.btn); mVideoView = (VideoView)findViewById(R.id.videowiew); btn.setOnClickListener(click); MediaController mController = new MediaController(this); mVideoView.setMediaController(mController);//设置一个控制条 } OnClickListener click = new OnClickListener() { @Override public void onClick(View v) { Uri uri = Uri.parse("http://10.0.245.2:9090/router?id=000000000000000000000566"); //Uri uri = Uri.parse("http://daily3gp.com/vids/family_guy_penis_car.3gp"); mVideoView.setVideoURI(uri); mVideoView.requestFocus(); mVideoView.start(); } };
注意要播放网络视频的话,还要在AndroidManifest.xml中加入:
<uses-permission android:name="android.permission.INTERNET" />
权限
显示的图像:
由于是播放的视频,所以截不到图像,中间是一个控制条,通过
MediaController mController = new MediaController(this); mVideoView.setMediaController(mController);
来加入,如果没有也可以播放,只是没有了这个控制条。这是android自带的控制条,具有暂停,快进,快退,一个进度显示条等。
完整工程代码可以到我的资源下载区下载。
http://download.csdn.net/detail/taoxugang2012/6500453
当然很多时候我们是不满足于使用别人的代码的,使用android的VideoView任然存在有些不足,比如说系统带的控制条太难看,全屏播放时无法全屏。
通过查看源码可以修改该VideoView类,最开始,将源代码拷贝过来用,会出现一些问题,修改了一些部分后就可用了,具体如下:
import java.io.IOException; import java.util.Map; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; //import android.content.res.Resources; import android.media.AudioManager; import android.media.MediaPlayer; import android.media.MediaPlayer.OnCompletionListener; import android.media.MediaPlayer.OnErrorListener; import android.media.MediaPlayer.OnInfoListener; import android.net.Uri; import android.util.AttributeSet; import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.MediaController; import android.widget.MediaController.MediaPlayerControl; public class VideoView extends SurfaceView implements MediaPlayerControl { private String TAG = "VideoView"; private Uri mUri; private Map<String, String> mHeaders; private int mDuration; private static final int STATE_ERROR = -1; private static final int STATE_IDLE = 0; private static final int STATE_PREPARING = 1; private static final int STATE_PREPARED = 2; private static final int STATE_PLAYING = 3; private static final int STATE_PAUSED = 4; private static final int STATE_PLAYBACK_COMPLETED = 5; private int mCurrentState = STATE_IDLE; private int mTargetState = STATE_IDLE; private SurfaceHolder mSurfaceHolder = null; private MediaPlayer mMediaPlayer = null; private int mVideoWidth; private int mVideoHeight; private int mSurfaceWidth; private int mSurfaceHeight; private MediaController mMediaController; private OnCompletionListener mOnCompletionListener; private MediaPlayer.OnPreparedListener mOnPreparedListener; private int mCurrentBufferPercentage; private OnErrorListener mOnErrorListener; private OnInfoListener mOnInfoListener; private int mSeekWhenPrepared; private boolean mCanPause; private boolean mCanSeekBack; private boolean mCanSeekForward; Context mContext; public VideoView(Context context) { super(context); mContext = context; initVideoView(); } public VideoView(Context context, AttributeSet attrs) { this(context, attrs, 0); mContext = context; initVideoView(); } public VideoView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mContext = context; initVideoView(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = getDefaultSize(mVideoWidth, widthMeasureSpec); int height = getDefaultSize(mVideoHeight, heightMeasureSpec); if (mVideoWidth > 0 && mVideoHeight > 0) { if ( mVideoWidth * height > width * mVideoHeight ) { height = width * mVideoHeight / mVideoWidth; } else if ( mVideoWidth * height < width * mVideoHeight ) { width = height * mVideoWidth / mVideoHeight; } } setMeasuredDimension(width, height); } @Override public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setClassName(VideoView.class.getName()); } @Override public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setClassName(VideoView.class.getName()); } public int resolveAdjustedSize(int desiredSize, int measureSpec) { int result = desiredSize; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); switch (specMode) { case MeasureSpec.UNSPECIFIED: result = desiredSize; break; case MeasureSpec.AT_MOST: result = Math.min(desiredSize, specSize); break; case MeasureSpec.EXACTLY: result = specSize; break; } return result; } private void initVideoView() { mVideoWidth = 0; mVideoHeight = 0; getHolder().addCallback(mSHCallback); getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); setFocusable(true); setFocusableInTouchMode(true); requestFocus(); mCurrentState = STATE_IDLE; mTargetState = STATE_IDLE; } public void setVideoPath(String path) { setVideoURI(Uri.parse(path)); } public void setVideoURI(Uri uri) { setVideoURI(uri, null); } /** * @hide */ public void setVideoURI(Uri uri, Map<String, String> headers) { mUri = uri; mHeaders = headers; mSeekWhenPrepared = 0; openVideo(); requestLayout(); invalidate(); } public void stopPlayback() { if (mMediaPlayer != null) { mMediaPlayer.stop(); mMediaPlayer.release(); mMediaPlayer = null; mCurrentState = STATE_IDLE; mTargetState = STATE_IDLE; } } private void openVideo() { if (mUri == null || mSurfaceHolder == null) { return; } Intent i = new Intent("com.android.music.musicservicecommand"); i.putExtra("command", "pause"); mContext.sendBroadcast(i); release(false); try { mMediaPlayer = new MediaPlayer(); mMediaPlayer.setOnPreparedListener(mPreparedListener); mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener); mDuration = -1; mMediaPlayer.setOnCompletionListener(mCompletionListener); mMediaPlayer.setOnErrorListener(mErrorListener); mMediaPlayer.setOnInfoListener(mOnInfoListener); mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener); mCurrentBufferPercentage = 0; mMediaPlayer.setDataSource(mContext, mUri, mHeaders); mMediaPlayer.setDisplay(mSurfaceHolder); mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mMediaPlayer.setScreenOnWhilePlaying(true); mMediaPlayer.prepareAsync(); mCurrentState = STATE_PREPARING; attachMediaController(); } catch (IOException ex) { Log.w(TAG, "Unable to open content: " + mUri, ex); mCurrentState = STATE_ERROR; mTargetState = STATE_ERROR; mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); return; } catch (IllegalArgumentException ex) { Log.w(TAG, "Unable to open content: " + mUri, ex); mCurrentState = STATE_ERROR; mTargetState = STATE_ERROR; mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); return; } } public void setMediaController(MediaController controller) { if (mMediaController != null) { mMediaController.hide(); } mMediaController = controller; attachMediaController(); } private void attachMediaController() { if (mMediaPlayer != null && mMediaController != null) { mMediaController.setMediaPlayer(this); View anchorView = this.getParent() instanceof View ? (View)this.getParent() : this; mMediaController.setAnchorView(anchorView); mMediaController.setEnabled(isInPlaybackState()); } } MediaPlayer.OnVideoSizeChangedListener mSizeChangedListener = new MediaPlayer.OnVideoSizeChangedListener() { public void onVideoSizeChanged(MediaPlayer mp, int width, int height) { mVideoWidth = mp.getVideoWidth(); mVideoHeight = mp.getVideoHeight(); if (mVideoWidth != 0 && mVideoHeight != 0) { getHolder().setFixedSize(mVideoWidth, mVideoHeight); requestLayout(); } } }; MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener() { public void onPrepared(MediaPlayer mp) { mCurrentState = STATE_PREPARED; mCanPause = true; if (mOnPreparedListener != null) { mOnPreparedListener.onPrepared(mMediaPlayer); } if (mMediaController != null) { mMediaController.setEnabled(true); } mVideoWidth = mp.getVideoWidth(); mVideoHeight = mp.getVideoHeight(); int seekToPosition = mSeekWhenPrepared; if (seekToPosition != 0) { seekTo(seekToPosition); } if (mVideoWidth != 0 && mVideoHeight != 0) { getHolder().setFixedSize(mVideoWidth, mVideoHeight); if (mSurfaceWidth == mVideoWidth && mSurfaceHeight == mVideoHeight) { if (mTargetState == STATE_PLAYING) { start(); if (mMediaController != null) { mMediaController.show(); } } else if (!isPlaying() && (seekToPosition != 0 || getCurrentPosition() > 0)) { if (mMediaController != null) { mMediaController.show(0); } } } } else { if (mTargetState == STATE_PLAYING) { start(); } } } }; private MediaPlayer.OnCompletionListener mCompletionListener = new MediaPlayer.OnCompletionListener() { public void onCompletion(MediaPlayer mp) { mCurrentState = STATE_PLAYBACK_COMPLETED; mTargetState = STATE_PLAYBACK_COMPLETED; if (mMediaController != null) { mMediaController.hide(); } if (mOnCompletionListener != null) { mOnCompletionListener.onCompletion(mMediaPlayer); } } }; private MediaPlayer.OnErrorListener mErrorListener = new MediaPlayer.OnErrorListener() { public boolean onError(MediaPlayer mp, int framework_err, int impl_err) { Log.d(TAG, "Error: " + framework_err + "," + impl_err); mCurrentState = STATE_ERROR; mTargetState = STATE_ERROR; if (mMediaController != null) { mMediaController.hide(); } if (mOnErrorListener != null) { if (mOnErrorListener.onError(mMediaPlayer, framework_err, impl_err)) { return true; } } if (getWindowToken() != null) { //Resources r = mContext.getResources(); int messageId; if (framework_err == MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK) { messageId = R.string.VideoView_error_text_invalid_progressive_playback; } else { messageId = R.string.VideoView_error_text_unknown; } new AlertDialog.Builder(mContext) .setMessage(messageId) .setPositiveButton(R.string.VideoView_error_button, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { if (mOnCompletionListener != null) { mOnCompletionListener.onCompletion(mMediaPlayer); } } }) .setCancelable(false) .show(); } return true; } }; private MediaPlayer.OnBufferingUpdateListener mBufferingUpdateListener = new MediaPlayer.OnBufferingUpdateListener() { public void onBufferingUpdate(MediaPlayer mp, int percent) { mCurrentBufferPercentage = percent; } }; /** * Register a callback to be invoked when the media file * is loaded and ready to go. * * @param l The callback that will be run */ public void setOnPreparedListener(MediaPlayer.OnPreparedListener l) { mOnPreparedListener = l; } /** * Register a callback to be invoked when the end of a media file * has been reached during playback. * * @param l The callback that will be run */ public void setOnCompletionListener(OnCompletionListener l) { mOnCompletionListener = l; } /** * Register a callback to be invoked when an error occurs * during playback or setup. If no listener is specified, * or if the listener returned false, VideoView will inform * the user of any errors. * * @param l The callback that will be run */ public void setOnErrorListener(OnErrorListener l) { mOnErrorListener = l; } /** * Register a callback to be invoked when an informational event * occurs during playback or setup. * * @param l The callback that will be run */ public void setOnInfoListener(OnInfoListener l) { mOnInfoListener = l; } SurfaceHolder.Callback mSHCallback = new SurfaceHolder.Callback() { public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { mSurfaceWidth = w; mSurfaceHeight = h; boolean isValidState = (mTargetState == STATE_PLAYING); boolean hasValidSize = (mVideoWidth == w && mVideoHeight == h); if (mMediaPlayer != null && isValidState && hasValidSize) { if (mSeekWhenPrepared != 0) { seekTo(mSeekWhenPrepared); } start(); } } public void surfaceCreated(SurfaceHolder holder) { mSurfaceHolder = holder; openVideo(); } public void surfaceDestroyed(SurfaceHolder holder) { mSurfaceHolder = null; if (mMediaController != null) mMediaController.hide(); release(true); } }; private void release(boolean cleartargetstate) { if (mMediaPlayer != null) { mMediaPlayer.reset(); mMediaPlayer.release(); mMediaPlayer = null; mCurrentState = STATE_IDLE; if (cleartargetstate) { mTargetState = STATE_IDLE; } } } @Override public boolean onTouchEvent(MotionEvent ev) { if (isInPlaybackState() && mMediaController != null) { toggleMediaControlsVisiblity(); } return false; } @Override public boolean onTrackballEvent(MotionEvent ev) { if (isInPlaybackState() && mMediaController != null) { toggleMediaControlsVisiblity(); } return false; } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { boolean isKeyCodeSupported = keyCode != KeyEvent.KEYCODE_BACK && keyCode != KeyEvent.KEYCODE_VOLUME_UP && keyCode != KeyEvent.KEYCODE_VOLUME_DOWN && keyCode != KeyEvent.KEYCODE_VOLUME_MUTE && keyCode != KeyEvent.KEYCODE_MENU && keyCode != KeyEvent.KEYCODE_CALL && keyCode != KeyEvent.KEYCODE_ENDCALL; if (isInPlaybackState() && isKeyCodeSupported && mMediaController != null) { if (keyCode == KeyEvent.KEYCODE_HEADSETHOOK || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE) { if (mMediaPlayer.isPlaying()) { pause(); mMediaController.show(); } else { start(); mMediaController.hide(); } return true; } else if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY) { if (!mMediaPlayer.isPlaying()) { start(); mMediaController.hide(); } return true; } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP || keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE) { if (mMediaPlayer.isPlaying()) { pause(); mMediaController.show(); } return true; } else { toggleMediaControlsVisiblity(); } } return super.onKeyDown(keyCode, event); } private void toggleMediaControlsVisiblity() { if (mMediaController.isShowing()) { mMediaController.hide(); } else { mMediaController.show(); } } public void start() { if (isInPlaybackState()) { mMediaPlayer.start(); mCurrentState = STATE_PLAYING; } mTargetState = STATE_PLAYING; } public void pause() { if (isInPlaybackState()) { if (mMediaPlayer.isPlaying()) { mMediaPlayer.pause(); mCurrentState = STATE_PAUSED; } } mTargetState = STATE_PAUSED; } public void suspend() { release(false); } public void resume() { openVideo(); } public int getDuration() { if (isInPlaybackState()) { if (mDuration > 0) { return mDuration; } mDuration = mMediaPlayer.getDuration(); return mDuration; } mDuration = -1; return mDuration; } public int getCurrentPosition() { if (isInPlaybackState()) { return mMediaPlayer.getCurrentPosition(); } return 0; } public void seekTo(int msec) { if (isInPlaybackState()) { mMediaPlayer.seekTo(msec); mSeekWhenPrepared = 0; } else { mSeekWhenPrepared = msec; } } public boolean isPlaying() { return isInPlaybackState() && mMediaPlayer.isPlaying(); } public int getBufferPercentage() { if (mMediaPlayer != null) { return mCurrentBufferPercentage; } return 0; } private boolean isInPlaybackState() { return (mMediaPlayer != null && mCurrentState != STATE_ERROR && mCurrentState != STATE_IDLE && mCurrentState != STATE_PREPARING); } public boolean canPause() { return mCanPause; } public boolean canSeekBackward() { return mCanSeekBack; } public boolean canSeekForward() { return mCanSeekForward; } }
这个代码没有做功能性修改,只是做了简单移植,编译通过,能够正常播放。
要使用自己定义的videoview,还需要在自己的xml写上完整控件路径
<com.example.listview.VideoView
android:id="@+id/videowiew"
android:layout_gravity="center_horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
这个部分,还不算完美,我之后还想把android的控制条重写。
相关文章推荐
- Android使用VideoView播放网络视频,获取网络视频缩略图
- android videoview的使用
- 关于android 中WebView使用Css
- Android使用VideoView播放网络视频
- 关于android中Videoview的选择
- 关于对Android的videoView和mediaController的吐槽
- 关于android.support.v7.widget.RecyclerView的使用,总是找不到类。
- Android 关于ViewPager结合碎片Fragment的简单使用
- 关于android使用design:25.1.0及以上包后,使用自定义behavivor(上拉隐藏,下拉显示)的view隐藏后不再显示的问题
- Android中关于Volley的使用(四)利用NetworkImageView来加载图片
- Android VideoView使用小记
- 关于Android使用Xutils的WebView保存Cookie登录
- Android中关于Volley的使用(四)利用NetworkImageView来加载图片
- android关于TabLayout+ViewPager结合使用的小Demo
- Android之使用VideoView组件播放一个简单的视频
- 关于android Activity中注解的使用,省去无用的findviewbyid....setonclick.....
- Android视频播放项目总结之 使用VideoView定义自己的视频播放器
- Android中关于Volley的使用(四)利用NetworkImageView来加载图片
- Android中关于RecycleView的使用,代替ListView,可以提高效率
- Android 关于WebView全方面的使用(项目应用篇)