热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

Android使用Vitamio打造自己的万能播放器(10)——本地播放(缩略图、视频信息、视频扫描服务)

本文主要介绍Android使用Vitamio开发播放器,这里主要讲解本地播放(缩略图、视频信息、视频扫描服务)等功能,有需要的小伙伴可以参考下

前言

 Vitamio是我们团队的诚意之作,除了要将VPlayer打造成Android最好的播放器,也要将Vitamio打造成Android最好的播放器组件。新版发布内测SDK虽然还有一些问题,但已经具备高可扩展性、便捷性和许多内置实用的功能,后续文章将继续深挖和介绍Vitamio的使用细节和方法。本章将提供显示缩略图、视频大小等视频信息,并介绍使用Vitamio内置的ContentProvider以及文件扫描服务。

注意

 本章ContentProvider在2012-8-31发布的SDK中已经不能使用,后续文章会更新用法。

  系列

1、Android 使用Vitamio打造自己的万能播放器(1)——准备  

2、Android 使用Vitamio打造自己的万能播放器(2)—— 手势控制亮度、音量、缩放 

3、Android 使用Vitamio打造自己的万能播放器(3)——本地播放(主界面、视频列表) 

4、Android 使用Vitamio打造自己的万能播放器(4)——本地播放(快捷搜索、数据存储)

5、Android 使用Vitamio打造自己的万能播放器(5)——在线播放(播放优酷视频)

6、Android 使用Vitamio打造自己的万能播放器(6)——在线播放(播放列表)

7、Android 使用Vitamio打造自己的万能播放器(7)——在线播放(下载视频)

8、Android 使用Vitamio打造自己的万能播放器(8)——细节优化

9、Android 使用Vitamio打造自己的万能播放器(9)——在线播放(在线电视)

正文

 一、目标

  1.1 获取视频缩略图等

   之前的文章都是自己扫描获取的视频文件信息,这里补充获取视频缩略图、视频宽带的代码,参加文章2.1部分。

  1.2 调用Vitamio的扫描服务

   新版SDK已经内置了视频扫描服务,提供了本地视频播放所需的全部数据。

 二、实现

  2.1 自己扫描获取视频的缩略图、视频宽高

 public static ArrayList batchBuildThumbnail(final Context ctx, final ArrayList files) {
 ArrayList result = new ArrayList();

 for (File f : files) {
 PFile pf = new PFile();
 try {
 if (f.exists() && f.canRead()) {
 //取出视频的一帧图像
 Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(ctx, f.getAbsolutePath(), Video.Thumbnails.MINI_KIND);
 if (bitmap == null) {
 //缩略图创建失败
 bitmap = Bitmap.createBitmap(ThumbnailUtils.TARGET_SIZE_MINI_THUMBNAIL_WIDTH, ThumbnailUtils.TARGET_SIZE_MINI_THUMBNAIL_HEIGHT, Bitmap.Config.RGB_565);
 Log.e(TAG, "batchBuildThumbnail createBitmap faild : " + f.getAbsolutePath());
 }

 pf.width = bitmap.getWidth();
 pf.height = bitmap.getHeight();

 //缩略图
 bitmap = ThumbnailUtils.extractThumbnail(bitmap, ThumbnailUtils.dipToPX(ctx, ThumbnailUtils.TARGET_SIZE_MICRO_THUMBNAIL_WIDTH), ThumbnailUtils.dipToPX(ctx, ThumbnailUtils.TARGET_SIZE_MICRO_THUMBNAIL_HEIGHT), ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
 if (bitmap != null) {
 File thum = new File(f.getParent(), f.getName() + ".jpg");
 pf.thumb = thum.getAbsolutePath();
 //thum.createNewFile();
 FileOutputStream iStream = new FileOutputStream(thum);
 bitmap.compress(Bitmap.CompressFormat.JPEG, 85, iStream);
 iStream.close();
 }

 if (bitmap != null)
 bitmap.recycle();
 }
 } catch (Exception e) {
 Log.e(TAG, e);
 continue;
 } finally {
 result.add(pf);
 }
 }

 return result;

 } 

代码说明:

    a). 缩略图的尺寸是可以调整的,大家可以看一下这个默认大小。

    b). 这里的代码是缩略图默认存在当前视频路径下面,并且文件名和视频名称一样,多加了一个jpg的后缀。

  2.2 调用Vitamio的视频扫描服务

   2.2.1  AndroidManifest.xml

 
 
 
 
 
 

 
 
 
 
 

 
 
 

 
 
 
 
 
 
 
 
 
 
 

代码说明:

     主要是MediaScannerService服务和MediaScannerReceiver监听器的注册。

   2.2.2  启动扫描服务(MainFragmentActivity

 if (!io.vov.vitamio.LibsChecker.checkVitamioLibs(this, getClass().getName(), R.string.init_decoders, R.raw.libarm))
 return;

 OPreference pref = new OPreference(this);
 //首次运行,扫描SD卡
 if (pref.getBoolean(PREF_KEY_FIRST, true)) {
 getApplicationContext().startService(new Intent(getApplicationContext(), MediaScannerService.class).putExtra(MediaScannerService.EXTRA_DIRECTORY, Environment.getExternalStorageDirectory().getAbsolutePath()));
 pref.putBooleanAndCommit(PREF_KEY_FIRST, false);
 }

代码说明:

     OPreference对象封装了SharedPreferences 存储数据。这里判断了是否首次启动应用,是的话启动视频扫描服务。

   2.2.3  获取数据(FragmentFile)

private static final String[] PROJECTION_MEDIA = new String[] { Video.Media._ID, Video.Media.TITLE, Video.Media.TITLE_KEY, Video.Media.SIZE, Video.Media.DURATION, Video.Media.DATA, Video.Media.WIDTH, Video.Media.HEIGHT };
 private static final String ORDER_MEDIA_TITLE = Video.Media.TITLE_KEY + " COLLATE NOCASE ASC";
 
 @Override
 public Loader onCreateLoader(int arg0, Bundle arg1) {
 Log.e(TAG, "onCreateLoader");
 return new CursorLoader(mParent, Video.Media.CONTENT_URI, PROJECTION_MEDIA, null, null, ORDER_MEDIA_TITLE);
 }

 @Override
 public void onLoadFinished(Loader arg0, Cursor newCursor) {
 Log.e(TAG, "onLoadFinished" + newCursor.getCount());
 mAdapter.swapCursor(newCursor);
 mListView.setSelectionFromTop(mVisiablePosition, mVisiableTop);
 }

 @Override
 public void onLoaderReset(Loader arg0) {
 Log.e(TAG, "onLoaderReset");
 mAdapter.swapCursor(null);
 }

代码说明:

   a). FragmentFile继承了LoaderCallbacks,相关的资料大家可以搜一下。

   b). 其中Video.Media.DATA 存的是视频的路径。

   c). 取缩略图的方法:

     Video.Thumbnails.getThumbnail(ctx.getApplicationContext(), ctx.getContentResolver(), _id, Video.Thumbnails.MICRO_KIND, null)

    这个"_id"就是Video.Media._ID,缩略图存在SD里,大家可以自己加一些缓存处理。

 三、注意事项

   3.1 启动视频服务扫描前,需要先确保解码库已经被解压,即调用代码:LibsChecker.checkVitamioLibs

   3.2 确保MediaScannerService与当前应用程序在一个进程中,即不要指定其android:process,否则无法使用视频扫描服务。

   3.3 目前获取扫描完成广播接收还有问题,即无法获知是否已经扫描完成。目前的办法是每次数据变更后5秒再去判断是否有该Service,没有了就表示已经扫描完成。参见方法MediaScannerReceiver.isServiceRunning。

  解码库

   https://bitbucket.org/ABitNo/ffmpegandroid

   http://vplayer.net      的首页底部已经给出链接,注意代码并不会实时同步,有需要的朋友可以参考一下。

 四、OPlayer

  4.1 下载

   请移步#Taocode(SVN):

   项目地址:http://code.taobao.org/p/oplayer

   SVN地址:http://code.taobao.org/svn/oplayer/

  4.2 更新

   a). 移动显示SD剩余容量至底部,并在其左边显示正在加载的图标。

   b). 保留原FragmentFile为FragmentFildOld,新版已经切换至使用Vitamio内置的视频扫描服务。

   c). 更换Adapter为CursorAdapter,同时更新A-Z的功能,参加代码更新。

   d). 新增了Preference,用于存储一般设置数据,例如是否首次启动。

 五、补充说明

  已经在SDK发布版本里面强调了许多,这里再强调一下:

  5.1 Vitamio相关项目不能同时存在同一个设备上,也不能与VPlayer共存,这是一个已知的BUG,下一版本会解决。

  5.2 Vitamio的示例工程需要在API Level14以上编译,但是最低版本可以支持7以上(android:minSdkVersion="7")。可以把values-v11和values-v14两个文件夹删除,Vitamio在目前项目使用中是兼容Android2.1以上版本,更低的没有试过,大家可以试一下。

  5.3 网络视频播放不了、很慢可能有以下几个原因:

   a). 你的网速不行

   b). 视频服务器不行,或者其带宽不够

   c). 可能是播放组件的问题,我们还在持续的改进,加大再网络播放这部分的优化,感谢理解和支持。

    遇到这种情况的时候,如果方便请把视频测试地址发给我们,并附上简要说明。(vplayer@yixia.com)

  5.4 一直停留在初始化解码包界面的问题

   一般出现这种情况,只有一个原因:你的设备上还有其他Vitamio的相关项目,参照5.1。

结束

 这篇文章耗费了我至少10个小时以上,昨晚熬到2点,为的是解决使用者心中的疑虑,最终更好的服务于用户。在文档不够全的情况下通过这种方式来与大家分享使用方法和技巧以及注意点,还请大家谅解。


推荐阅读
  • 网络运维工程师负责确保企业IT基础设施的稳定运行,保障业务连续性和数据安全。他们需要具备多种技能,包括搭建和维护网络环境、监控系统性能、处理突发事件等。本文将探讨网络运维工程师的职业前景及其平均薪酬水平。 ... [详细]
  • 深入理解Cookie与Session会话管理
    本文详细介绍了如何通过HTTP响应和请求处理浏览器的Cookie信息,以及如何创建、设置和管理Cookie。同时探讨了会话跟踪技术中的Session机制,解释其原理及应用场景。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 在Linux系统中配置并启动ActiveMQ
    本文详细介绍了如何在Linux环境中安装和配置ActiveMQ,包括端口开放及防火墙设置。通过本文,您可以掌握完整的ActiveMQ部署流程,确保其在网络环境中正常运行。 ... [详细]
  • RecyclerView初步学习(一)
    RecyclerView初步学习(一)ReCyclerView提供了一种插件式的编程模式,除了提供ViewHolder缓存模式,还可以自定义动画,分割符,布局样式,相比于传统的ListVi ... [详细]
  • PHP 5.5.0rc1 发布:深入解析 Zend OPcache
    2013年5月9日,PHP官方发布了PHP 5.5.0rc1和PHP 5.4.15正式版,这两个版本均支持64位环境。本文将详细介绍Zend OPcache的功能及其在Windows环境下的配置与测试。 ... [详细]
  • 基于KVM的SRIOV直通配置及性能测试
    SRIOV介绍、VF直通配置,以及包转发率性能测试小慢哥的原创文章,欢迎转载目录?1.SRIOV介绍?2.环境说明?3.开启SRIOV?4.生成VF?5.VF ... [详细]
  • 探讨如何真正掌握Java EE,包括所需技能、工具和实践经验。资深软件教学总监李刚分享了对毕业生简历中常见问题的看法,并提供了详尽的标准。 ... [详细]
  • 配置Windows操作系统以确保DAW(数字音频工作站)硬件和软件的高效运行可能是一个复杂且令人沮丧的过程。本文提供了一系列专业建议,帮助你优化Windows系统,确保录音和音频处理的流畅性。 ... [详细]
  • 本文介绍了在Windows环境下使用pydoc工具的方法,并详细解释了如何通过命令行和浏览器查看Python内置函数的文档。此外,还提供了关于raw_input和open函数的具体用法和功能说明。 ... [详细]
  • MySQL缓存机制深度解析
    本文详细探讨了MySQL的缓存机制,包括主从复制、读写分离以及缓存同步策略等内容。通过理解这些概念和技术,读者可以更好地优化数据库性能。 ... [详细]
  • 本题涉及一棵由N个节点组成的树(共有N-1条边),初始时所有节点均为白色。题目要求处理两种操作:一是改变某个节点的颜色(从白变黑或从黑变白);二是查询从根节点到指定节点路径上的第一个黑色节点,若无则输出-1。 ... [详细]
  • 并发编程:深入理解设计原理与优化
    本文探讨了并发编程中的关键设计原则,特别是Java内存模型(JMM)的happens-before规则及其对多线程编程的影响。文章详细介绍了DCL双重检查锁定模式的问题及解决方案,并总结了不同处理器和内存模型之间的关系,旨在为程序员提供更深入的理解和最佳实践。 ... [详细]
  • 本文介绍如何使用布局文件在Android应用中排列多行TextView和Button,使其占据屏幕的特定比例,并提供示例代码以帮助理解和实现。 ... [详细]
  • 本文探讨了在Windows Server 2008环境下配置Tomcat使用80端口时遇到的问题,包括端口被占用、多项目访问失败等,并提供详细的解决方法和配置建议。 ... [详细]
author-avatar
85中互动_715
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有