VideoView 播放视频

VideoView 简 介

  • 除了使用 MediaPlayer + SurfaceView 播放视频的方式,可以参考《 MediaPlayer 播放音频与视频》,还可以使用 VideoView来直接播放视频。
  • VideoView 类将视频的显示和与控制集于一身,使得可以借助它就可以轻松的完成一个简易的视频播放器。
  • VideoView 底层仍然是使用 MediaPlayer 来对视频文件进行控制。
  • android.widget.VideoView  继承于 android.view.SurfaceView,常用 API 如下:

    int getCurrentPosition():获取当前播放的位置。
    int getDuration():获取当前播放视频的总长度。
    isPlaying():当前VideoView是否在播放视频。
    void pause():暂停
    void seekTo(int msec):从第几毫秒开始播放。
    void resume():重新播放。
    void setVideoPath(String path):以文件路径的方式设置 VideoView 播放的视频源。
    void setVideoURI(Uri uri):以 Uri 的方式设置 VideoView 播放的视频源,可以是网络 Uri 或本地 Uri。
    void start():开始播放。
    void stopPlayback():停止播放,并释放资源
    setMediaController(MediaController controller):设置MediaController控制器。
    setOnCompletionListener(MediaPlayer.onCompletionListener l):监听播放完成的事件。
    setOnErrorListener(MediaPlayer.OnErrorListener l):监听播放发生错误时候的事件。
    setOnPreparedListener(MediaPlayer.OnPreparedListener l)::监听视频装载完成的事件。

播放 res/raw 目录下的文件

  • 现在先播放 res/raw 目录下的文件

  • 布局文件 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>
  • MainActivity.java 文件内容如下:
package com.example.administrator.helloworld;

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:为当前类的所在的包路径
         * 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

播放设备本地文件

  • 现在来播放手机存储中的视频文件,如下所示播放手机存储根目录下的 246.mp4 文件
  • Android 底层是 Linux 系统,所以文件目录与 Linux 一样,而与 Windows 系统不一样,右下图可知,整个手机存储的根目录就叫 “ /storage/emulated/0” 

  • 布局文件仍然和上面播放 res/raw 目录下的文件时一致
  • MainActivity.java 文件内容如下:
package com.example.administrator.helloworld;

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();
    }
}
  • 注意 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" />

  • 控制台输出,可见 电源存放的标准目录下手机存储根目录下的 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

  • 至此播放手机本地视频的功能就完成了。其中涉及的一些重要 API 介绍如下:
  • Android 应用开发中,常使用 Environment 类去获取外部存储目录,在访问外部存储之前一定要先判断外部存储是否已经是可使用(已挂载&可使用)状态
  • 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 存储媒体没有挂载。

  • 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)

猜你喜欢

转载自blog.csdn.net/wangmx1993328/article/details/82803305