Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

Android控件--VideoView

$
0
0

1、简介

VideoView顾名思义就是播放视频的控件,使用VideoView是我们除了MediaPlayer + surfaceView之外播放视频的另一种写法,它继承自surfaceView,所以对UI的更新处理不太需要我们担心。

视频播放原理:
系统会首先确定视频的格式,然后得到视频的编码..然后对编码进行解码,得到一帧一帧的图像,最后在画布上进行迅速更新,显然需要在独立的线程中完成,这时就需要使用surfaceView了。surfaceView在这里就不说了,大家应该都知道是在另一个线程中去做UI更新操作。

2、xml配置

<?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:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context="com.ht.videoplayer.MainActivity">

    <VideoView
        android:id="@+id/videoview"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>
    <Button
        android:id="@+id/button"
        android:text="播放"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

在xml中我们只要确定VideoView的宽高即可,其它的我们多用代码来实现。

3、API方法

构造方法:

VideoView(Context context)  
VideoView(Context context, AttributeSet attrs)  
VideoView(Context context, AttributeSet attrs, int defStyle)  

VideoView就跟我们自定义控件时的控件差不多,如果在代码中实例化一个View会调用第一个构造函数,如果在xml中定义会调用第二个构造函数,而第三个函数系统是不调用的,要由View(我们自定义的或系统预定义的View)显式调用,比如在这里我们在第二个构造函数中调用了第三个构造函数,并将style传给了第三个参数。

第三个参数的意义就如同它的名字所说的,是默认的Style,只是这里没有说清楚,这里的默认的Style是指它在当前Application或Activity所用的Theme中的默认Style。

//视频是否可以暂停。  
boolean canPause() 

//视频是否可以后退  
boolean canSeekBackward() 

//视频是否可以快进。  
boolean canSeekForward()

//获取缓冲百分比  
int getBufferPercentage()

//获取当前播放的位置  
int getCurrentPosition() 

//获取播放视频的总时间  
int getDuration()  

//判断视频是否处于播放状态  
boolean isPlaying()  
boolean onKeyDown (int keyCode, KeyEvent event)

KeyEvent.Callback.onKeyMultiple() 的默认实现。如果视图可用并可按, 当按下 KEYCODE_DPAD_CENTER 或 KEYCODE_ENTER 时执行视图的按下事件。

keyCode 表示按下的键的、在 KEYCODE_ENTER 中定义的键盘代码
event KeyEvent对象,定义了按钮动作

如果处理了事件,返回真。如果允许下一个事件接受器处理该事件,可以返回假。

boolean onTouchEvent (MotionEvent ev)

实现该方法来处理触屏事件。event 触屏事件,如果事件已经处理返回True,否则返回false。

boolean onTrackballEvent (MotionEvent ev)

实现这个方法去处理轨迹球的动作事件,轨迹球相对于上次事件移动的位置能用MotionEvent.getX() 和 MotionEvent.getY()函数取回。对应用户按下一次方向键, 他们通常作为一次移动处理(为了表现来自轨迹球的更小粒度的移动信息,他们返回小数)。ev 动作的事件。

//让视频播放暂停
void pause () 
int resolveAdjustedSize (int desiredSize, int measureSpec)

取得调整后的尺寸。如果measureSpec对象传入的模式是UNSPECIFIED那么返回的是desiredSize。如果measureSpec对象传入的模式是AT_MOST,返回的将是desiredSize和measureSpec对象的尺寸两者中最小的那个。如果measureSpec对象传入的模式是EXACTLY,那么返回的是measureSpec对象中的尺寸大小值。

关于specMode的几种模式,我在Android–自定义控件解析(二)这篇博客讲解onMeasure()方法的时候有介绍过,有兴趣的朋友可以看看。

//从暂停中恢复 
void resume()
//跳转到指定的播放位置
void seekTo(int msec)
//设置媒体控制器,方便控制视频播放  
void setMediaController(MediaController controller)
//媒体在播放完毕时的回调函数  
void setOnCompletionListener(MediaPlayer.OnCompletionListener l)

//在设置或播放过程中发生错误时调用的回调函数。如果未指定回调函数, 或回调函数返回假,VideoView 会通知用户发生了错误。
//经常会碰到视频编码格式不支持的情况,若不想弹出提示框就返回true;
void setOnErrorListener(MediaPlayer.OnErrorListener l)

//在媒体文件加载完毕,可以播放时调用的回调函数
void setOnPreparedListener(MediaPlayer.OnPreparedListener l)
//设置视频文件的路径
void setVideoPath(String path)

//设置视频文件的统一资源标识符
void setVideoURI(Uri uri)
//开始播放视频文件
void start()
//停止回放视频文件
void stopPlayback()
//挂起视频文件的播放
void suspend()

通过suspend()函数,可使线程进入停滞状态。通过suspend()使线程进入停滞状态后,除非收到resume()消息,否则该线程不会变回可执行状态。

4、使用实例

在上面的API方法中我们可以看到有两种方法可以加载到视频文件,一种就是在本地路径中找文件,另一种是在网络上加载视频。要注意文件名小写字母,格式: 3gp,mp4等,flv的不一定支持。

分别用的方法是setVideoPath(String Path)和 setVideoURL(URL url),我们这篇博客只讲如何用VideoView播放视频,先看在本地如何加载视频。

可以看到我们已经把ht.mp4这个视频放到sdcard目录下了。当然要想访问sdcard,还需要权限,如果你的android系统是6.0或以上,你需要手动添加,不了解的朋友可以看我的博客Android–权限管理

private VideoView mVideoView;
private Button play;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    sdcardPermission();

    play = (Button) findViewById(R.id.button);

    String path = Environment.getExternalStorageDirectory().getPath() + File.separator + "ht.mp4";

    mVideoView = (VideoView) findViewById(R.id.videoview);
    mVideoView.setMediaController(new MediaController(this));
    mVideoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
        @Override
        public void onCompletion(MediaPlayer mp) {
            Toast.makeText(MainActivity.this, "播放完成", Toast.LENGTH_SHORT).show();
        }
    });

    mVideoView.setVideoPath(path);

    play.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mVideoView.start();
        }
    });

}

可以看到没什么问题,我们再来网络上的,这里我用得不是Internet上的视频,而是用Tomcat搭建了个本地服务器,看这篇博客的朋友想要做事例也可以搭个本地服务器,不然就是在网络上找视频。

自然即使是本地服务器,你也是要添加网络权限的,不过INTERNET不是危险权限,所以不用手动添加。

而代码只要修改path为URI,执行方法换一下就OK啦。

Uri uri = Uri.parse("http://14.215.177.37:8080/video/ht.mp4");
mVideoView.setVideoURI(uri);

放在res/raw中的视频文件也可以使用setVideoURI(uri)

Uri rawUri = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.ht);
mVideoView.setVideoURI(rawUri);

最后的结果自然也不会有变化。

结束语:本文仅用来学习记录,参考查阅。

作者:HardWorkingAnt 发表于2017/5/20 11:07:20 原文链接
阅读:29 评论:0 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>