博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android视频播放之VideoView
阅读量:4545 次
发布时间:2019-06-08

本文共 6858 字,大约阅读时间需要 22 分钟。

Android视频播放之VideoView

 

1、VideoView类介绍

  Android的VideoView组件可以从不同的来源(例如资源文件或内容提供器)读取图像,计算和维护视频的画面尺寸以使其适用于任何布局管理器,并提供一些诸如缩放、着色之类的显示选项,包含在widget下面:android.widget.VideoView。Android中视屏播放框架如下图:

  从图中可以看出,VideoView组件进行视频播放的过程可以分为三步:

    (1)JAVA Framework层,应用程序进来之后到VideoView,再经过Surface;

    (2)Native Framework层,先到SurfaceFlinger,然后到OverlayHal,同时借助了PVPlayer;

    (3)Driver层,利用Main framebuffer和Video Plane进行播放;

  VideoView组件的类继承与接口实现情况为:

    继承:public class VideoView extends SurfaceView

    接口:implements MediaController.MediaPlayerControl

  而从Object开始的继承层次如下:

    java.lang.Object

      android.view.View

        android.view.SurfaceView

          android.widget.VideoView

  VideoView类的构造函数有三个:

  (1)public VideoView(Context context),创建一个默认属性的VideoView实例。参数context为视图运行的应用程序上下文,通过它可以访问当前主题、资源等等。注:以下描述中重复参数的解释就不给出了。

  (2)public VideoView(Context context, AttributeSet attrs),创建一个带有attrs属性的VideoView实例。attrs用于视图的 XML 标签属性集合。

  (3)public VideoView(Context context, AttributeSet attrs, int defStyle),创建一个带有attrs属性,并且指定其默认样式的VideoView实例。参数defStyle为应用到视图的默认风格,如果为 0 则不应用(包括当前主题中的)风格,该值可以是当前主题中的属性资源,也可以是明确的风格资源ID。

  比较常用的共有方法有播放start()、暂停pause()等,具体描述与用法见后面测试部分。

 

2、视频播放代码

       先给出一个简单的测试案例,程序中以File和Uri两种形式来给VideoView组件加载手机SD卡中的视频资源。资源类型为MP4,使用手机自带摄像机录制,完整路径名为“/mnt/sdcard/Pictures/video.mp4”。在代码采用的是读取系统路径的方式:Environment.getExternalStorageDirectory() + "/Pictures/video.mp4"。

  另外说明一点,利用Uri对网络资源进行读取的方式和本地资源类似,只是资源名称的形式不同。如:

1 Uri uri = Uri.parse("rtsp://v2.cache2.c.youtube.com/CjgLENy73wIaLwm3JbT_%ED%AF%80%ED%B0%819HqWohMYESARFEIJbXYtZ29vZ2xlSARSB3Jlc3VsdHNg_vSmsbeSyd5JDA==/0/0/0/video.3gp");

  文件格式3gp也是VideoView组件支持格式中的一种。

  由于要对手机中的文件进行读取,所以必须在AndroidManifest.xml文件中添加用户权限:

1 
2
3

      程序中用到的String变量封装在了string.xml中:

1 
2
VideoView0803
3 4
Hello world!
5
Settings
6 7
PlayCard
8
StopCard
9
PlayUri
10
StopUri
11

  界面上的组件由一个VideoView、两个Button,一个TextView组成,布局文件代码如下:

1 
7 8
16 17
25 26
34 35
46 47

  其中,VideoView组件videoView用于视频内容的播放,Button组件startFile和startUri分别以File和Uri形式打开视频文件,TextView组件fileName用于显示完整路径名(标注资源的来历,对于该例子没这个必要)。运行前的界面图:

       主文件MainActivity完整代码如下:

1 package com.dylan_wang.videoview0803;  2   3 import android.app.Activity;  4 import android.net.Uri;  5 import android.os.Bundle;  6 import android.os.Environment;  7 import android.view.Menu;  8 import android.view.MenuItem;  9 import android.view.View; 10 import android.widget.Button; 11 import android.widget.MediaController; 12 import android.widget.TextView; 13 import android.widget.VideoView; 14  15 import java.io.File; 16  17  18 public class MainActivity extends Activity { 19  20     private String filename = null; 21     private Button startCard = null; 22     private Button startUri = null; 23     private TextView fileName = null; 24     private VideoView video = null; 25     private MediaController media = null; 26  27     @Override 28     protected void onCreate(Bundle savedInstanceState) { 29         super.onCreate(savedInstanceState); 30         setContentView(R.layout.activity_main); 31  32         filename = Environment.getExternalStorageDirectory() + "/Pictures/video.mp4"; 33  34         startCard = (Button)findViewById(R.id.startCard); 35         startUri = (Button)findViewById(R.id.startUri); 36         fileName = (TextView)findViewById(R.id.fileName); 37         video = (VideoView)findViewById(R.id.videoView); 38         media = new MediaController(MainActivity.this); 39  40         startCard.setOnClickListener(new View.OnClickListener() { 41             @Override 42             public void onClick(View v) { 43                 playVideoFromFile(); 44             } 45         }); 46  47         startUri.setOnClickListener(new View.OnClickListener() { 48             @Override 49             public void onClick(View v) { 50                 openVideoFromUri(); 51             } 52         }); 53     } 54  55     private void playVideoFromFile(){ 56         if(startCard.getText().toString().equals("PlayCard")) { 57             File file = new File(filename); 58             if (file.exists()) { 59                 //将VideoView与MediaController进行关联 60                 video.setVideoPath(file.getAbsolutePath()); 61                 video.setMediaController(media); 62                 media.setMediaPlayer(video); 63                 //让VideoView获取焦点 64                 video.requestFocus(); 65                 video.start(); 66                 startCard.setText(R.string.pauseCard); 67                 fileName.setText(filename); 68             } 69         } 70         else { 71             video.pause(); 72             startCard.setText(R.string.startCard); 73         } 74     } 75  76     private void openVideoFromUri(){ 77         if(startUri.getText().toString().equals("PlayUri")) { 78             Uri uri = Uri.parse(filename); 79             video.setVideoURI(uri); 80             video.setMediaController(media); 81             media.setMediaPlayer(video); 82             //同上 83             video.requestFocus(); 84             video.start(); 85             startUri.setText(R.string.pauseUri); 86             fileName.setText(filename); 87         } 88         else { 89             video.pause(); 90             startUri.setText(R.string.startUri); 91         } 92     } 93  94     @Override 95     public boolean onCreateOptionsMenu(Menu menu) { 96         // Inflate the menu; this adds items to the action bar if it is present. 97         getMenuInflater().inflate(R.menu.menu_main, menu); 98         return true; 99     }100 101     @Override102     public boolean onOptionsItemSelected(MenuItem item) {103         // Handle action bar item clicks here. The action bar will104         // automatically handle clicks on the Home/Up button, so long105         // as you specify a parent activity in AndroidManifest.xml.106         int id = item.getItemId();107 108         //noinspection SimplifiableIfStatement109         if (id == R.id.action_settings) {110             return true;111         }112 113         return super.onOptionsItemSelected(item);114     }115 }

  

3、运行结果分析

  OK,现在点击界面上的任何一个按钮就可以播放视频文件了。由于两个按钮的响应只是读取资源的方式不同,播放效果是一样的,所以下面只给出点击左边按钮PLAYCARD后的播放图:

      

  左边这张为程序运行后,没有任何操作的图片,右边是正在播放视频的图片。

  可以发现两个有趣的现象:

    1、在布局文件activity_main.xml中已将videoView组件在父容器中的设置为水平居中(android:layout_centerHorizontal="true"),而且运行初始界面也是正常的,但是视频播放后,该组件就偏向了左边;

    2、播放过程中会有系统的控制栏出现在下方,可以点击进行视屏的播放控制,但是在测试很不稳定,出现一两秒就会消失;

  针对第一个问题,查了一些资料,有人说是因为默认情况下,如果视频分辨率小于设备的屏幕分辨率,VideoView在播放视频时都是在左上角显示的,将VideoView组件的gravity属性设置为center即可。但是在xml文件及UI编辑属性栏均没有找到VideoView组件有该属性,难道和版本有关?也有人说和底层的Player有关,虽然没有进行替换测试,但感觉这个原因比较靠谱。至于第二个问题,暂时没有找到合理的解释,以后继续找吧。

  有知道真实原因的大神,欢迎一起讨论啊!

转载于:https://www.cnblogs.com/tgyf/p/4700177.html

你可能感兴趣的文章
Java生成javadoc
查看>>
ZedGraph控件的使用--属性和例子代码
查看>>
文件管理
查看>>
webpack
查看>>
Atitit.swift 的新特性 以及与java的对比 改进方向attilax 总结
查看>>
Atitit 图像处理 平滑 也称 模糊, 归一化块滤波、高斯滤波、中值滤波、双边滤波)...
查看>>
Android Camera——拍照(转自http://vaero.blog.51cto.com/4350852/779942)
查看>>
Java Web项目移植
查看>>
11月的第一天
查看>>
2011简单总结
查看>>
android的Environment类,记录一下
查看>>
工作流Activiti5流程变量 任务变量 setVariables 跟 setVariablesLocal区别
查看>>
c语言诊断_断言库函数#include<assert.h>
查看>>
input type="file"获取文件名方法
查看>>
强力上攻后,缓解期结束,MACD死叉的案例
查看>>
Linux文件权限
查看>>
js替换字符串中特殊字符
查看>>
第一单元OO总结
查看>>
让 Windows7 - 64bit 支持 VC++ 6.0 的解决方法(无法启动此程序,因为计算机中丢失 MSVCRTD.dll。尝试重新安装该程序以解决此问题)...
查看>>
SSH 整合及注意事项
查看>>