目录
VideoView 简 介
1、除了使用 MediaPlayer + SurfaceView 播放视频的方式,可以参考《 MediaPlayer 播放音频与视频》,还可以使用 VideoView来直接播放视频。
2、VideoView 类将视频的显示和与控制集于一身,使得可以借助它就可以轻松的完成一个简易的视频播放器。
3、VideoView 底层仍然是使用 MediaPlayer 来对视频文件进行控制。
4、android.widget.VideoView 继承于 android.view.SurfaceView,常用 API 如下:
int getCurrentPosition():获取当前播放的位置,单位毫秒
int getDuration():获取当前播放视频的总长度,单位毫秒
isPlaying():当前VideoView是否在播放视频。
void pause():暂停,视频资源未绑定就绪,或者已经暂停时,再次 pause不会有影响
void seekTo(int msec):从第几毫秒开始播放。
void resume():重新播放。
void setVideoPath(String path):以文件路径的方式设置 VideoView 播放的视频源。
void setVideoURI(Uri uri):以 Uri 的方式设置 VideoView 播放的视频源,可以是网络 Uri 或本地 Uri。
void start():开始播放,视频资源未绑定就绪,或者已经在播放时,再次 start 不会有影响
void stopPlayback():停止播放,并释放资源
setMediaController(MediaController controller):设置MediaController控制器。
setOnCompletionListener(MediaPlayer.onCompletionListener l):监听播放完成的事件。
setOnErrorListener(MediaPlayer.OnErrorListener l):监听播放发生错误时候的事件。
setOnPreparedListener(MediaPlayer.OnPreparedListener l)::监听视频装载完成的事件。
播放 res/raw 目录下的文件
1、现在先播放 res/raw 目录下的文件
2、布局文件 activity_main.xml 文件内容如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<VideoView
android:id="@+id/videoView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
3、MainActivity.java 文件内容如下:
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.MediaController;
import android.widget.VideoView;
/**
* 一个应用程序可以有1个或多个活动,而没有任何限制。
* 每个为应用程序所定义的活动都需要在 AndroidManifest.xml 中声明,应用的主活动的意图过滤器标签中需要包含 MAIN 动作和 LAUNCHER 类别
* 如果 MAIN 动作还是 LAUNCHER 类别没有在活动中声明,那么应用程序的图标将不会出现在主屏幕的应用列表中。
* implements View.OnClickListener:用于绑定单击事件
* implements SurfaceHolder.Callback:用于监测 surface 的状态,重写其三个方法
* android.view.SurfaceHolder 是接口,Callback 是 SurfaceHolder 的子接口
*/
public class MainActivity extends AppCompatActivity {
/**
* android.widget.VideoView:视频播放器控件
*/
private VideoView videoView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindViews();
}
private void bindViews() {
videoView = findViewById(R.id.videoView);
/**播放 res/raw 目录下的文件
* android.resource:// :前缀固定
* com.example.administrator.helloworld:为当前类的所在的包路径,可以使用 String packageName = getPackageName(); 动态获取
* R.raw.la_isla:最后接 res/raw 目录中的文件名
* */
videoView.setVideoURI(Uri.parse("android.resource://com.example.administrator.helloworld/" + R.raw.la_isla));
/**
* 为 VideoView 视图设置媒体控制器,设置了之后就会自动由进度条、前进、后退等操作
*/
videoView.setMediaController(new MediaController(this));
/**视频准备完成时回调
* */
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
Log.i("tag", "--------------视频准备完毕,可以进行播放.......");
}
});
/**
* 视频播放完成时回调
*/
videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
Log.i("tag", "------------------视频播放完毕..........");
/**播放完成时,再次循环播放*/
videoView.start();
}
});
/**
* 视频播放发送错误时回调
*/
videoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.i("tag", "---------------------视频播放失败...........");
return false;
}
});
/**开始播放视频
* */
videoView.start();
}
}
控制台输出:
I/tag: --------------视频准备完毕,可以进行播放.......
I/VideoView: Playback Start begin
I/VideoView: Playback Start end
I/Timeline: Timeline: Activity_idle id: android.os.BinderProxy@30a217f9 time:156278265
W/MediaPlayer: info/warning (3, 0)
I/ViewRootImpl: CPU Rendering VSync enable = true
I/ViewRootImpl: CPU Rendering VSync enable = true
I/tag: ------------------视频播放完毕..........
I/VideoView: Playback Start begin
I/VideoView: Playback Start end
播放设备本地文件
1、现在来播放手机存储中的视频文件,如下所示播放手机存储根目录下的 246.mp4 文件
2、Android 底层是 Linux 系统,所以文件目录与 Linux 一样,而与 Windows 系统不一样,右下图可知,整个手机存储的根目录就叫 “ /storage/emulated/0”
3、布局文件仍然和上面播放 res/raw 目录下的文件时一致
4、MainActivity.java 文件内容如下:
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.MediaController;
import android.widget.VideoView;
/**
* 一个应用程序可以有1个或多个活动,而没有任何限制。
* 每个为应用程序所定义的活动都需要在 AndroidManifest.xml 中声明,应用的主活动的意图过滤器标签中需要包含 MAIN 动作和 LAUNCHER 类别
* 如果 MAIN 动作还是 LAUNCHER 类别没有在活动中声明,那么应用程序的图标将不会出现在主屏幕的应用列表中。
* implements View.OnClickListener:用于绑定单击事件
* implements SurfaceHolder.Callback:用于监测 surface 的状态,重写其三个方法
* android.view.SurfaceHolder 是接口,Callback 是 SurfaceHolder 的子接口
*/
public class MainActivity extends AppCompatActivity {
/**
* android.widget.VideoView:视频播放器控件
*/
private VideoView videoView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindViews();
}
private void bindViews() {
/**绑定视频视图*/
videoView = findViewById(R.id.videoView);
/**
* 播放手机本地文件:
* 通过静态方法 Environment.getExternalStorageState() 来获取外部存储的状态,如果程序需要在外部存储里面读写数据,必须要先判断
* Environment.MEDIA_MOUNTED: 存储媒体已经挂载,并且挂载点可读/写。
* Environment.getExternalStorageDirectory():得到的值是 /storage/emulated/0 即手机存储的根目录
*/
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
videoView.setVideoPath(Environment.getExternalStorageDirectory() + "/246.mp4");
/**
* Environment.DIRECTORY_MOVIES:获取手机中电影存放的标准目录
* Environment.DIRECTORY_PICTURES:获取手机中图片存放的标准目录
*/
String moviesDir = Environment.DIRECTORY_MOVIES;
String picturesDir = Environment.DIRECTORY_PICTURES;
Log.d("--------------->>", moviesDir);
Log.d("--------------->>", picturesDir);
}
/**
* 为 VideoView 视图设置媒体控制器,设置了之后就会自动由进度条、前进、后退等操作
*/
videoView.setMediaController(new MediaController(this));
/**视频准备完成时回调
* */
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
Log.i("tag", "--------------视频准备完毕,可以进行播放.......");
}
});
/**
* 视频播放完成时回调
*/
videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
Log.i("tag", "------------------视频播放完毕..........");
/**播放完成时,再次循环播放*/
videoView.start();
}
});
/**
* 视频播放发送错误时回调
*/
videoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.i("tag", "---------------------视频播放失败...........");
return false;
}
});
/**开始播放视频
* */
videoView.start();
}
}
5、注意 Android 系统与 Windows 系统不同,Windows 可以直接读写系统上的文件,而 Android 必须先设置权限才行,这也就是平时在手机安装 App 的时候,会提示 应用将要获取哪些权限的原因。修改 AndroidManifest.xml 文件即可:
<!--添加外部存储的读/写权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
6、控制台输出,可见 电源存放的标准目录下手机存储根目录下的 Movies 目录,而图片存储的标准目录是手机存储根目录下的 Pictures 目录:
D/--------------->>: Movies
Pictures
........
I/tag: --------------视频准备完毕,可以进行播放.......
I/VideoView: Playback Start begin
I/VideoView: Playback Start end
I/ViewRootImpl: CPU Rendering VSync enable = true
I/ViewRootImpl: CPU Rendering VSync enable = true
I/tag: ------------------视频播放完毕..........
I/VideoView: Playback Start begin
I/VideoView: Playback Start end
7、至此播放手机本地视频的功能就完成了。其中涉及的一些重要 API 介绍如下:
8、Android 应用开发中,常使用 Environment 类去获取外部存储目录,在访问外部存储之前一定要先判断外部存储是否已经是可使用(已挂载&可使用)状态
Environment 类详解
1、android.os.Environment 类中提供了几个静态常量用于标识外部存储的状态,这些状态都是 String 类型,如下所示:
MEDIA_BAD_REMOVAL 在没有挂载前存储媒体已经被移除。
MEDIA_CHECKING 正在检查存储媒体。
MEDIA_MOUNTED 存储媒体已经挂载,并且挂载点可读/写。
MEDIA_MOUNTED_READ_ONLY 存储媒体已经挂载,挂载点只读。
MEDIA_NOFS 存储媒体是空白或是不支持的文件系统。
MEDIA_REMOVED 存储媒体被移除。
MEDIA_SHARED 存储媒体正在通过USB共享。
MEDIA_UNMOUNTABLE 存储媒体无法挂载。
MEDIA_UNMOUNTED 存储媒体没有挂载。
2、android.os.Environment 类中还提供了 Android 系统的标准目录路径,以 String 类型提供,如下所示:
DIRECTORY_ALARMS 系统提醒铃声存放的标准目录。
DIRECTORY_DCIM 相机拍摄照片和视频的标准目录。
DIRECTORY_DOWNLOADS 下载的标准目录。
DIRECTORY_MOVIES 电影存放的标准目录。
DIRECTORY_MUSIC 音乐存放的标准目录。
DIRECTORY_NOTIFICATIONS 系统通知铃声存放的标准目录。
DIRECTORY_PICTURES 图片存放的标准目录
DIRECTORY_PODCASTS 系统广播存放的标准目录。
DIRECTORY_RINGTONES 系统铃声存放的标准目录。static File getDataDirectory() 获得data的目录(/data)。
static File getDownloadCacheDirectory() 获得下载缓存目录。(/cache)
static File getExternalStorageDirectory() 获得外部存储媒体目录。(/mnt/sdcard or /storage/sdcard0)
static File getRootDirectory() 获得系统主目录(/system)
播放网络在线视频
1、现在来播放网络上在线的视频,效果图如下:
2、activity_main.xml 布局文件内容仍然和上面一致,MainActivity.java 文件内容如下:
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.MediaController;
import android.widget.VideoView;
/**
* 一个应用程序可以有1个或多个活动,而没有任何限制。
* 每个为应用程序所定义的活动都需要在 AndroidManifest.xml 中声明,应用的主活动的意图过滤器标签中需要包含 MAIN 动作和 LAUNCHER 类别
* 如果 MAIN 动作还是 LAUNCHER 类别没有在活动中声明,那么应用程序的图标将不会出现在主屏幕的应用列表中。
* implements View.OnClickListener:用于绑定单击事件
* implements SurfaceHolder.Callback:用于监测 surface 的状态,重写其三个方法
* android.view.SurfaceHolder 是接口,Callback 是 SurfaceHolder 的子接口
*/
public class MainActivity extends AppCompatActivity {
/**
* android.widget.VideoView:视频播放器控件
*/
private VideoView videoView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindViews();
}
private void bindViews() {
/**
* 香港卫视:http://live.hkstv.hk.lxdns.com/live/hks/playlist.m3u8
* CCTV1高清直播:http://ivi.bupt.edu.cn/hls/cctv1hd.m3u8
* CCTV3高清直播:http://ivi.bupt.edu.cn/hls/cctv3hd.m3u8
* CCTV5高清直播:http://ivi.bupt.edu.cn/hls/cctv5hd.m3u8
* CCTV5+高清直播:http://ivi.bupt.edu.cn/hls/cctv5phd.m3u8
* CCTV6高清直播:http://ivi.bupt.edu.cn/hls/cctv6hd.m3u8
* 苹果提供的测试源(点播):http://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/gear2/prog_index.m3u8
* 微博视频:https://f.us.sinaimg.cn/000BFP1Zgx07nNMQWH4A01040200bazV0k010.mp4?label=mp4_hd&template=640x360.28&Expires=1537611622&ssig=hAwEQKCJkz&KID=unistore,video
* 直播视频精进度条能看到当前播放时间,看不到总共多少时间
*/
String url = "https://f.us.sinaimg.cn/000BFP1Zgx07nNMQWH4A01040200bazV0k010.mp4?label=mp4_hd&template=640x360.28&Expires=1537611622&ssig=hAwEQKCJkz&KID=unistore,video";
videoView = findViewById(R.id.videoView);
/**
* 设置播放的资源路径,使用 setVideoURI(Uri uri) 或者 setVideoPath(String path)(底层也是调用的 serVideoURL(Uri uri))
*/
videoView.setVideoPath(url);
/**为控件设置焦点*/
videoView.requestFocus();
/**
* 为 VideoView 视图设置媒体控制器,设置了之后就会自动由进度条、前进、后退等操作
*/
videoView.setMediaController(new MediaController(this));
/**视频准备完成时回调
* */
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
Log.i("tag", "--------------视频准备完毕,可以进行播放.......");
}
});
/**
* 视频播放完成时回调
*/
videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
Log.i("tag", "------------------视频播放完毕..........");
}
});
/**
* 视频播放发送错误时回调
*/
videoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.i("tag", "---------------------视频播放失败...........");
return false;
}
});
/**开始播放视频
* */
videoView.start();
}
}
3、如同播放本地文件,需要获取手机读写权限一样,进行网络通信时,也需要获取手机的网络权限,因为连接网络是要使用流量或者 WIFI 的,必须用户授权,所以同样在 AndroidManifest.xml 中添加权限:
<!--添加外部存储的读/写权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><!--添加网络访问权限-->
<uses-permission android:name="android.permission.INTERNET" />
uses-permission 权限统计
Android Manifest功能与权限描述大全
1、Android Manifest 是 Android 程序开发中控制各项功能权限的核心文件,该参考表详尽描述了 Android Manifest 各个参数项的名称与功能。来源网址:http://tools.jb51.net/table/AndroidManifest