Android VideoView 播放视频

本文详细介绍了Android中VideoView的使用方法,包括播放res/raw目录下的文件、设备本地文件及网络在线视频。解析了VideoView的API,如控制播放、设置监听器等,并介绍了Environment类的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

VideoView 简 介

播放 res/raw 目录下的文件

播放设备本地文件

Environment 类详解

播放网络在线视频

uses-permission 权限统计


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

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蚩尤后裔-汪茂雄

芝兰生于深林,不以无人而不芳。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值