一、VideoView及其相关组件总结
在Android中,播放视频有2种方式,第一种方式是使用MediaPlayer结合SurfaceView来播放,通过MediaPlayer来控制视频的播放、暂停、进度等,而通过SurfaceView来显示视频内容;第二种方式是使用VideoView来播放,这个类其实也是继承了SurfaceView类,并且实现了MediaController.MediaPlayerController这个用于控制媒体播放的接口,另外在VideoView上还有一个用于对媒体播放进行控制的面板,包括快进、快退、播放、暂停按钮以及一个进度条。使用VideoView播放视频的好处是简单因为它已经帮我们实现了SurfaceView以及控制方法,开发过程中只需直接拿来使用就可以了,但它的缺点是不够灵活。而是用MediaPlayer结合SurfaceView来播放视频的话,好处是可以更灵活的对其进行自定义,缺点是难度较大。
1.1通过VideoView播放视频步骤:
1、在界面布局文件中定义VideoView组件,或在程序中创建VideoView组件
2、在Activity中获取布局文件中的组件并设置相应的监听;
3、调用VideoView的如下两个方法来加载指定的视频:
(1)setVideoPath(String path):加载path文件代表的视频
(2)setVideoURI(URI uri):加载uri所对应的视频
在使用setVideoURI(URI uri)方法之前要设置网络视频路径
4、调用VideoView的start()、pause()、resume()、stopPlayback()方法控制视频的播放(开始、暂停、继续、停止),VideoView的getDuration()可以返回视频的长度,可以结合VideoView的resume()方法进行记忆播放和缓存播放。
1.2 VideoView常用方法
Android VideoView类为我们提供了十分方便的视频播放API,其主要方法有:
方法名称 |
说明 |
void start() |
开始播放 |
void stopPlayback() |
停止播放 |
void pause() |
暂停 |
void resume() |
重新播放 |
void seekTo(int msec) |
从第几毫秒开始播放 |
int getCurrentPosition() |
获取当前播放位置 |
int getDuration() |
获取当前视频总长度 |
boolean isPlaying() |
当前VideoView是否在播放视频 |
void setVideoPath(String path) |
以文件路径的方式设置VideoView播放的视频源 |
void setVideoURI(URI uri) |
以Uri的方式设置视频源,可以是网络Uri或本地Uri |
setMediaCotroller(MediaController controller) |
设置MediaController控制器
|
setOnCompletionListener(MediaPlayer.onCompletionListener l) |
监听播放完成的事件 |
setOnErrorListener(MediaPlayer.OnErrorListener l) |
监听播放发生错误时候的事件 |
setOnPreparedListener(MediaPlayer.OnPreparedListener l) |
监听视频装载完成的事件 |
1.3 Media Controller类
Media Controller类为我们提供了一个悬浮的操作栏,包含了播放,暂停,快进,快退,上一个,下一个等功能键。还有拖动进度条至某一处也可以实现。在使用前VideoView和MeidaController需要相互指定控件。
Mdedia Controller类包含的内置方法有:
方法名称 |
说明 |
boolean isShowing() |
当前悬浮控制栏是否显示。 |
void setMediaPlayer(MediaController.MediaPlayerControl player) |
设置控制的组件 |
void hide() |
隐藏MeidaController |
void show() |
显示MeidaController |
void show(int timeout) |
设置MidiaController显示的时间,以毫秒计算。如果设置为0则一直到调用hide()方法隐藏 |
void setPrevNextListeners(View.OnClickListener next,View.OnClickListener prev) |
设置上一个视频下一个视频的切换事件 |
默认情况下,Media Controller悬浮显示3s后隐藏,触摸响应的VideoView呼出。默认上一个,下一个按钮隐藏。
1.4 视频格式
1.4.1 Android支持的视频编码格式
1.4.2 VideoView支持的影片格式
在实际测试中过程中,发现了一些由VideoView发出的Toast警告,内容写着不支持影片格式,以致无法播放。VideoView仅能播放progressive streamable(渐进式流)的影片,一般的mp4或3gp若不采用progressive streamable模式转文件的影片,是无法被VideoView通过网络播放的,但假如存放在local端(如储存卡)则不在此限。
1.5 VideoView的监听处理
开发过程中使用的VideoView监听一共有3个:setOnCompletionListener(MediaPlayer.onCompletionListener l)、setOnErrorListener(MediaPlayer.OnErrorListener l)、setOnPreparedListener(MediaPlayer.OnPreparedListener l)
1.5.1 setOnCompletionListener(MediaPlayer.onCompletionListener l)
setOnCompletionListener(MediaPlayer.onCompletionListener l)用于监听视频播放完成后的事件
1.5.2 setOnErrorListener(MediaPlayer.OnErrorListener l)
setOnErrorListener(MediaPlayer.OnErrorListener l)用于监听VideoView在使用过程中出现的各种错误。
错误常数:
- MEDIA_ERROR_IO
- 文件不存在或错误,或网络不可访问错误
- 值: -1004 (0xfffffc14)
- MEDIA_ERROR_MALFORMED
- 流不符合有关标准或文件的编码规范
- 值: -1007 (0xfffffc11)
- MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK
- 视频流及其容器不适用于连续播放视频的指标(例如:MOOV原子)不在文件的开始.
- 值: 200 (0x000000c8)
- MEDIA_ERROR_SERVER_DIED
- 媒体服务器挂掉了。此时,程序必须释放MediaPlayer 对象,并重新new 一个新的。
- 值: 100 (0x00000064)
- MEDIA_ERROR_TIMED_OUT
- 一些操作使用了过长的时间,也就是超时了,通常是超过了3-5秒
- 值: -110 (0xffffff92)
- MEDIA_ERROR_UNKNOWN
- 未知错误
- 值: 1 (0x00000001)
- MEDIA_ERROR_UNSUPPORTED
- 比特流符合相关编码标准或文件的规格,但媒体框架不支持此功能
- 值: -1010 (0xfffffc0e)
- what int: 标记的错误类型:
- MEDIA_ERROR_UNKNOWN
- MEDIA_ERROR_SERVER_DIED
- extra int: 标记的错误类型.
- MEDIA_ERROR_IO
- MEDIA_ERROR_MALFORMED
- MEDIA_ERROR_UNSUPPORTED
- MEDIA_ERROR_TIMED_OUT
- MEDIA_ERROR_SYSTEM (-2147483648) - low-level system error.
1.5.3 setOnPreparedListener(MediaPlayer.OnPreparedListener l)
setOnPreparedListener(MediaPlayer.OnPreparedListener l)用于监听视频装在完成后的事件
二、视频旋转
在网上查询了众多的关于屏幕旋转的方法。总结起来可以分为4种。在介绍之前要先了解默认情况下Android屏幕旋转机制(当然是在手机本身屏幕旋转功能开启的时候才能实现,自己在开发过程中一直发现开发视频不能随着手机一起旋转,弄了几个小时才发现是自己Android本身自带的旋转按钮没有开启):
默认情况下,当用户的重力感应器打开后,屏幕旋转方向会导致当前activity发生onDestory->onCreate,这样会重新构造当前activity和界面布局,如果是在Camera界面,则表现为卡顿或者黑屏一段时间。如果是在横竖屏UI设计方面,那么想很好的支持屏幕旋转,则建议在res中建立layout-land和layport两个文件夹,把横屏和竖屏的文件分别放入对应的layout文件夹中。
2.1 AndroidMainfest.xml设置
如果单单想设置横屏或者竖屏,那么只需添加横竖屏代码:
优点:即使屏幕旋转,Actiity也不会重新onCreate。
缺点:屏幕只有一个方向
2.2 代码动态设置
如果需要动态改变横竖屏设置,只要在代码中调用setRequestedOrientation()函数:
优点:可以随意动态设置,满足人们为改变横竖屏的要求,同时满足横竖屏UI不同的设计需求
缺点:如果改变设置,那么Activity会被销毁,重新构建,即重新onCreate;
2.3 重写onCongigurationChanged
使用此方法可以避免旋转屏幕时Activity被不断的onCreate情况(这种情况下往往造成屏幕切换时的卡顿)。
首先,在AndroidMainfest.xml中添加configChanges:
注意:keyboardHidden表示键盘辅助功能隐藏,如果你的开发API等级等于或高于13,还需要设置screenSize,因为screenSize会在屏幕旋转时改变
然后,在Activity中重写onConfigurationChanged方法,这个方法将会在屏幕旋转变化时,进行监听处理:
优点:可以随时监听屏幕旋转变化,并对应做出相应操作
缺点:它只能一次旋转90°,如果一下子旋转180°,onConfigurationChanged函数不会被调用。
2.4 结合OrientationEventListener,自定义旋转监听设置
这种方法由于自定义回掉接口暂时不明白,在这里暂不总结。
可以参考网站:http://www.jb51.net/article/64735.htm
三、误按返回操作
为了防止用户误按返回键而退出播放,可以在程序中重写onKeyDown方法。在这个方法中来处理用户点击返回键的动作:例如只有用户在短时间内点击两次返回键才真正退出播放。
四、设置手机全屏
4.1 最常用的设置全屏方法
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 设置无标题 requestWindowFeature(Window.FEATURE_NO_TITLE); // 设置全屏 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_main); }
使用上述方法注意:requestWindowFeature()方法一定要在setContentView()前面,否则会报错;
4.2 AndroidManifest中配置
利用Android提供的内置的Theme就可以了。
五、设置屏幕显示方向
当不定义横竖屏的情况下,这个app会随着手机的转向设置变化而变化,而我们对于横竖屏切换肯定要做相应的事情,可以如下方法去做:
if (getResources().getConfiguration().orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) { // 处理横屏下要做的事 } else { // 处理竖屏下要做的事情 }
在这个视频软件中我要做到一个点击按钮让手机旋转的功能,就是用到了上面的代码:
六、取消全屏的方法
getWindow().clearFlags( WindowManager.LayoutParams.FLAG_FULLSCREEN);
七、Android系统自带样式
android:theme="@android:style/Theme.Dialog" 将一个Activity显示为能话框模式
android:theme="@android:style/Theme.NoTitleBar" 不显示应用程序标题栏
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" 不显示应用程序标题栏,并全屏
android:theme="Theme.Light" 背景为白色
android:theme="Theme.Light.NoTitleBar" 白色背景并无标题栏
android:theme="Theme.Light.NoTitleBar.Fullscreen" 白色背景,无标题栏,全屏
android:theme="Theme.Black" 背景黑色
android:theme="Theme.Black.NoTitleBar" 黑色背景并无标题栏
android:theme="Theme.Black.NoTitleBar.Fullscreen" 黑色背景,无标题栏,全屏
android:theme="Theme.Wallpaper" 用系统桌面为应用程序背景
android:theme="Theme.Wallpaper.NoTitleBar" 用系统桌面为应用程序背景,且无标题栏
android:theme="Theme.Wallpaper.NoTitleBar.Fullscreen" 用系统桌面为应用程序背景,无标题栏,全屏
android:theme="Translucent" 透明背景
android:theme="Theme.Translucent.NoTitleBar" 透明背景并无标题
android:theme="Theme.Translucent.NoTitleBar.Fullscreen" 透明背景并无标题,全屏
android:theme="Theme.Panel" 面板风格显示
android:theme="Theme.Light.Panel" 平板风格显示
八、小结:
由于太久的时间没有接触Android开发,很多Android开发的东西都忘记了,代码中具体的方法在这里不做一一总结,而在另外一篇文档中总结说明。