Android视频播放之VideoView

这篇具有很好参考价值的文章主要介绍了Android视频播放之VideoView。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、VideoView类介绍

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

android 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对网络资源进行读取的方式和本地资源类似,只是资源名称的形式不同。如:

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 <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
2 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
3 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

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

 1 <resources>
 2     <string name="app_name">VideoView0803</string>
 3 
 4     <string name="hello_world">Hello world!</string>
 5     <string name="action_settings">Settings</string>
 6 
 7     <string name="startCard">PlayCard</string>
 8     <string name="pauseCard">StopCard</string>
 9     <string name="startUri">PlayUri</string>
10     <string name="pauseUri">StopUri</string>
11 </resources>

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

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
 3     android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
 4     android:paddingRight="@dimen/activity_horizontal_margin"
 5     android:paddingTop="@dimen/activity_vertical_margin"
 6     android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
 7 
 8     <Button
 9         android:layout_width="wrap_content"
10         android:layout_height="wrap_content"
11         android:text="@string/startCard"
12         android:id="@+id/startCard"
13         android:layout_alignParentBottom="true"
14         android:layout_alignParentStart="true"
15         android:textColor="#00f" />
16 
17     <Button
18         android:layout_width="wrap_content"
19         android:layout_height="wrap_content"
20         android:text="@string/startUri"
21         android:id="@+id/startUri"
22         android:layout_alignBottom="@+id/startCard"
23         android:layout_alignParentEnd="true"
24         android:textColor="#f00" />
25 
26     <VideoView
27         android:layout_width="wrap_content"
28         android:layout_height="wrap_content"
29         android:id="@+id/videoView"
30         android:layout_alignParentStart="true"
31         android:layout_alignParentTop="true"
32         android:layout_above="@+id/startUri"
33         android:layout_centerHorizontal="true" />
34 
35     <TextView
36         android:layout_width="wrap_content"
37         android:layout_height="wrap_content"
38         android:textAppearance="?android:attr/textAppearanceMedium"
39         android:text="Resource Path"
40         android:id="@+id/fileName"
41         android:layout_alignTop="@+id/startCard"
42         android:layout_alignParentBottom="true"
43         android:layout_toEndOf="@+id/startCard"
44         android:gravity="center_vertical"
45         android:textColor="#000"/>
46 
47 </RelativeLayout>

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

android videoview,android,音视频

       主文件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     @Override
102     public boolean onOptionsItemSelected(MenuItem item) {
103         // Handle action bar item clicks here. The action bar will
104         // automatically handle clicks on the Home/Up button, so long
105         // as you specify a parent activity in AndroidManifest.xml.
106         int id = item.getItemId();
107 
108         //noinspection SimplifiableIfStatement
109         if (id == R.id.action_settings) {
110             return true;
111         }
112 
113         return super.onOptionsItemSelected(item);
114     }
115 }

3、运行结果分析

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

  

android videoview,android,音视频

    

android videoview,android,音视频

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

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

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

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

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

  有知道真实原因的大神,欢迎一起讨论啊!文章来源地址https://www.toymoban.com/news/detail-828150.html

到了这里,关于Android视频播放之VideoView的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android 使用ViewPager2+ExoPlayer+VideoCache 实现仿抖音视频翻页播放

    1. 实现效果    效果图中,视频没有铺满 是因为使用了ExoPlayer的RESIZE_MODE_FIT模式, 虽然使用RESIZE_MODE_FILL模式可以填充整个父布局,但是本Demo中使用的视频源本身就不适合全屏,会把视频拉伸,效果不好。 抖音上的视频源应该都有严格的宽高尺寸,才能做到全屏有很好的效

    2023年04月09日
    浏览(41)
  • Android音视频编码(2)

    Android本身提供了音视频编解码工具,很多时候是不需要第三方工具的,比如 ffmpeg , OpenCV 等,在android中引入第三库比较复杂,在Android音视频编码中介绍了如何引入第三方库libpng来进行进行图片处理,同时引入这些第三方库,是程序结构变得复杂。 本文介绍的音视频编解码利

    2024年01月17日
    浏览(52)
  • Android音视频-MediaCodec

    原文:https://mp.weixin.qq.com/s?__biz=MzU3NTA3MDU1OQ==mid=2247484865idx=1sn=174b8ca702466e83e72c7115d91b06eachksm=fd298df1ca5e04e7b2df9dc9f21e5cfe3e910204c905d8605f648ce6f6404432a83ae52a23a3scene=178cur_album_id=1638784435628064770#rd MediaCodec 支持处理三种数据类型,分别是压缩数据(compressed data)、原始音频数据(raw audio d

    2023年04月08日
    浏览(80)
  • Android-音视频学习系列-(九)Android-端实现-rtmp-推流

    视频画面的采集主要是使用各个平台提供的摄像头 API 来实现的,在为摄像头设置了合适的参数之后,将摄像头实时采集的视频帧渲染到屏幕上提供给用户预览,然后将该视频帧传递给编码通道,进行编码。 1. 权限配置 2. 打开摄像头 2.1 检查摄像头 public static void checkCameraSe

    2024年04月12日
    浏览(73)
  • Android音视频学习系列(九) — Android端实现rtmp推流

    Android音视频学习系列(一) — JNI从入门到精通 Android音视频学习系列(二) — 交叉编译动态库、静态库的入门 Android音视频学习系列(三) — Shell脚本入门 Android音视频学习系列(四) — 一键编译32/64位FFmpeg4.2.2 Android音视频学习系列(五) — 掌握音频基础知识并使用AudioTrack、OpenSL ES渲

    2024年02月09日
    浏览(50)
  • Android-音视频学习系列-(九)Android-端实现-rtmp-推流(2)

    配置好之后,检查一下 AudioRecord 当前的状态是否可以进行录制,可以通过 AudioRecord##getState 来获取当前的状态: STATE_UNINITIALIZED 还没有初始化,或者初始化失败了 STATE_INITIALIZED 已经初始化成功了。 2. 开启采集 创建好 AudioRecord 之后,就可以开启音频数据的采集了,可以通过调

    2024年04月12日
    浏览(62)
  • Android音视频: 引入FFmpeg

    本文你可以了解到 本文将介绍如何将上一篇文章编译出来的  FFmpeg so  库,引入到  Android  工程中,并验证  so  是否可以正常使用。 一、开启 Android 原生 C/C++ 支持 在过去,通常使用  makefile  的方式在项目中引入  C/C++  代码支持,随着  Android Studio  的普及, makefile  的

    2024年02月02日
    浏览(71)
  • Android音视频之协议介绍

    本文对音视频的协议起源做详细介绍,学习之后可以加深对音视频知识的了解。 这里的音视频不仅针对Android平台,其他平台也通用。 一般是指以某种格式封装了音视频数据的文件 常见的音频格式:mp3、wma、avi、rm、rmvb、flv、mpg、mov、mkv等。 常见的视频格式:rmvb、rm、wmv、

    2023年04月19日
    浏览(57)
  • Android之 集成音视频通话

    一,背景 1.1 最近接收一个即时通讯二开项目,即时通讯部分用的XMPP协议,音视频则是集成的国外的开源免费库jitsi-meet-sdk-2.4.0-4.aar,是基于WebRTC的开源框架。但客户想要微信那种页面的排版,后来经研究jitsi是不能修改UI的,UI部分是用混合框架ReactNative写的,这样难度就大了

    2024年02月12日
    浏览(65)
  • Android音视频开发 - MediaMetadataRetriever 相关

    MediaMetadataRetriever 是android中用于从媒体文件中提取元数据新的类. 可以获取音频,视频和图像文件的各种信息,如时长,标题,封面等. 需要申请 读写权限 . 这里我使用的是本地路径, 需要注意的是如果路径文件不存在,会抛出 IllegalArgumentException,具体的源码如下: 根据keyCode返回keyC

    2024年04月08日
    浏览(54)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包