关于android的VideoView的使用

2024-03-18 09:48
文章标签 android 使用 videoview

本文主要是介绍关于android的VideoView的使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Android自带了一个VideoView,用来播放视频和网络视频,它是继承SurfaceView使用MediaPlayer来做播放的类。

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"><Buttonandroid: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;@Overrideprotected 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() {@Overridepublic 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


当然很多时候我们是不满足于使用别人的代码的,使用androidVideoView任然存在有些不足,比如说系统带的控制条太难看,全屏播放时无法全屏。

 

通过查看源码可以修改该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();}@Overrideprotected 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);}@Overridepublic void onInitializeAccessibilityEvent(AccessibilityEvent event) {super.onInitializeAccessibilityEvent(event);event.setClassName(VideoView.class.getName());}@Overridepublic 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;}}}@Overridepublic boolean onTouchEvent(MotionEvent ev) {if (isInPlaybackState() && mMediaController != null) {toggleMediaControlsVisiblity();}return false;}@Overridepublic boolean onTrackballEvent(MotionEvent ev) {if (isInPlaybackState() && mMediaController != null) {toggleMediaControlsVisiblity();}return false;}@Overridepublic 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的使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/821956

相关文章

SpringBoot中使用Flux实现流式返回的方法小结

《SpringBoot中使用Flux实现流式返回的方法小结》文章介绍流式返回(StreamingResponse)在SpringBoot中通过Flux实现,优势包括提升用户体验、降低内存消耗、支持长连... 目录背景流式返回的核心概念与优势1. 提升用户体验2. 降低内存消耗3. 支持长连接与实时通信在Sp

python使用库爬取m3u8文件的示例

《python使用库爬取m3u8文件的示例》本文主要介绍了python使用库爬取m3u8文件的示例,可以使用requests、m3u8、ffmpeg等库,实现获取、解析、下载视频片段并合并等步骤,具有... 目录一、准备工作二、获取m3u8文件内容三、解析m3u8文件四、下载视频片段五、合并视频片段六、错误

gitlab安装及邮箱配置和常用使用方式

《gitlab安装及邮箱配置和常用使用方式》:本文主要介绍gitlab安装及邮箱配置和常用使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1.安装GitLab2.配置GitLab邮件服务3.GitLab的账号注册邮箱验证及其分组4.gitlab分支和标签的

SpringBoot3应用中集成和使用Spring Retry的实践记录

《SpringBoot3应用中集成和使用SpringRetry的实践记录》SpringRetry为SpringBoot3提供重试机制,支持注解和编程式两种方式,可配置重试策略与监听器,适用于临时性故... 目录1. 简介2. 环境准备3. 使用方式3.1 注解方式 基础使用自定义重试策略失败恢复机制注意事项

nginx启动命令和默认配置文件的使用

《nginx启动命令和默认配置文件的使用》:本文主要介绍nginx启动命令和默认配置文件的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录常见命令nginx.conf配置文件location匹配规则图片服务器总结常见命令# 默认配置文件启动./nginx

在Windows上使用qemu安装ubuntu24.04服务器的详细指南

《在Windows上使用qemu安装ubuntu24.04服务器的详细指南》本文介绍了在Windows上使用QEMU安装Ubuntu24.04的全流程:安装QEMU、准备ISO镜像、创建虚拟磁盘、配置... 目录1. 安装QEMU环境2. 准备Ubuntu 24.04镜像3. 启动QEMU安装Ubuntu4

使用Python和OpenCV库实现实时颜色识别系统

《使用Python和OpenCV库实现实时颜色识别系统》:本文主要介绍使用Python和OpenCV库实现的实时颜色识别系统,这个系统能够通过摄像头捕捉视频流,并在视频中指定区域内识别主要颜色(红... 目录一、引言二、系统概述三、代码解析1. 导入库2. 颜色识别函数3. 主程序循环四、HSV色彩空间详解

Windows下C++使用SQLitede的操作过程

《Windows下C++使用SQLitede的操作过程》本文介绍了Windows下C++使用SQLite的安装配置、CppSQLite库封装优势、核心功能(如数据库连接、事务管理)、跨平台支持及性能优... 目录Windows下C++使用SQLite1、安装2、代码示例CppSQLite:C++轻松操作SQ

Python常用命令提示符使用方法详解

《Python常用命令提示符使用方法详解》在学习python的过程中,我们需要用到命令提示符(CMD)进行环境的配置,:本文主要介绍Python常用命令提示符使用方法的相关资料,文中通过代码介绍的... 目录一、python环境基础命令【Windows】1、检查Python是否安装2、 查看Python的安

Python并行处理实战之如何使用ProcessPoolExecutor加速计算

《Python并行处理实战之如何使用ProcessPoolExecutor加速计算》Python提供了多种并行处理的方式,其中concurrent.futures模块的ProcessPoolExecu... 目录简介完整代码示例代码解释1. 导入必要的模块2. 定义处理函数3. 主函数4. 生成数字列表5.