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

简介:

前言

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

 

注意

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

  

声明
  欢迎转载,但请保留文章原始出处:) 
    博客园:http://www.cnblogs.com
    农民伯伯: http://over140.cnblogs.com 


系列 

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

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

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

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

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

 

正文 

一、目标

1.1 获取视频缩略图等

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

1.2 调用Vitamio的扫描服务 

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

 

 

二、实现

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

复制代码
     /**  批量提取视频的缩略图已经视频的宽高  */
     public  static ArrayList<PFile> batchBuildThumbnail( final Context ctx,  final ArrayList<File> files) {
        ArrayList<PFile> result =  new ArrayList<PFile>();

         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 

复制代码
         < receiver  android:name ="io.vov.vitamio.MediaScannerReceiver"   >
             < intent-filter >
                 < action  android:name ="android.intent.action.BOOT_COMPLETED"   />
             </ intent-filter >
             < intent-filter >
                 < action  android:name ="android.intent.action.MEDIA_MOUNTED"   />

                 < data  android:scheme ="file"   />
             </ intent-filter >
             < intent-filter >
                 < action  android:name ="com.yixia.vitamio.action.MEDIA_SCANNER_SCAN_FILE"   />
                 < action  android:name ="com.yixia.vitamio.action.MEDIA_SCANNER_SCAN_DIRECTORY"   />

                 < data  android:scheme ="file"   />
             </ intent-filter >
         </ receiver >

         < service
            
android:name ="io.vov.vitamio.MediaScannerService"
            android:exported
="false"   >
             < intent-filter >
                 < action  android:name ="io.vov.vitamio.IMediaScannerService"   />
             </ intent-filter >
         </ service >
        
         < service
            
android:name ="io.vov.vitamio.VitamioService"
            android:exported
="false"   >
             < intent-filter >
                 < action  android:name ="io.vov.vitamio.IVitamioService"   />
             </ intent-filter >
         </ service >
复制代码

  代码说明:

主要是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<Cursor> onCreateLoader( int arg0, Bundle arg1) {
        Log.e(TAG, "onCreateLoader");
         return  new CursorLoader(mParent, Video.Media.CONTENT_URI, PROJECTION_MEDIA,  nullnull, ORDER_MEDIA_TITLE);
    }

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

    @Override
     public  void onLoaderReset(Loader<Cursor> arg0) {
        Log.e(TAG, "onLoaderReset");
        mAdapter.swapCursor( null);
    }
复制代码

  代码说明:

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

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。

 

四、Vitamio

已建立Vitamio开发者联盟官方QQ群!群号为:246969281
注意:目前仅接受已经开发基于Vitamio产品的开发者申请加入,申请理由请填写产品的名称和链接!
官方微博:http://weibo.com/vitamio 

解码库

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发布版本里面强调了许多,这里再强调一下:

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

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

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

a). 你的网速不行

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

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

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

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

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

  

结束 

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


转载:http://www.cnblogs.com/over140/archive/2012/07/21/2598729.html

目录
相关文章
|
2月前
|
缓存 Java Shell
Android 系统缓存扫描与清理方法分析
Android 系统缓存从原理探索到实现。
81 15
Android 系统缓存扫描与清理方法分析
|
2月前
|
Java 程序员 开发工具
Android|修复阿里云播放器下载不回调的问题
虽然 GC 带来了很多便利,但在实际编码时,我们也需要注意对象的生命周期管理,该存活的存活,该释放的释放,避免因为 GC 导致的问题。
40 2
|
2月前
|
Java Unix Linux
Android Studio中Terminal运行./gradlew clean build提示错误信息
遇到 `./gradlew clean build`命令执行出错时,首先应检查错误信息的具体内容,这通常会指向问题的根源。从权限、环境配置、依赖下载、版本兼容性到项目配置本身,逐一排查并应用相应的解决措施。记住,保持耐心,逐步解决问题,往往复杂问题都是由简单原因引起的。
369 2
|
4月前
|
Android开发
Android 利用MediaPlayer实现音乐播放
本文提供了一个简单的Android MediaPlayer音乐播放示例,包括创建PlayerActivity、配置AndroidManifest.xml和activity_player.xml布局,以及实现播放和暂停功能的代码。
38 0
Android 利用MediaPlayer实现音乐播放
|
4月前
|
编解码 网络协议 开发工具
Android平台如何实现多路低延迟RTSP|RTMP播放?
本文档详细介绍了大牛直播SDK在Android平台上实现RTSP与RTMP流媒体播放及录像功能的技术细节。早在2015年,SDK的第一版就已经支持了多实例播放,并且通过简单的实例封装就能轻松实现。文档中提供了代码示例,展示了如何开启播放、停止播放以及开始和停止录像等功能。此外,SDK还提供了丰富的配置选项,例如设置录像目录、文件大小限制、转码选项等。总结部分列出了该SDK的关键特性,包括但不限于高稳定性和低延迟的播放能力、多实例支持、事件回调、硬解码支持、网络状态监控以及复杂的网络环境处理等。这些功能使得SDK能够应对各种应用场景,特别是在对延迟和稳定性有极高要求的情况下表现优异。
116 5
|
4月前
|
编解码 网络协议 vr&ar
Android平台下VR头显如何低延迟播放4K以上超高分辨率RTSP|RTMP流
这段内容讲述了VR头显中实现高分辨率视频播放的技术背景与实现方法,并强调了其重要性。高分辨率对于提升VR体验至关重要,它能提供更清晰的画面、增强沉浸感、补偿透镜放大效应,并维持宽广视场角下的图像质量。文中提到的大牛直播SDK具备极低的延迟(200-400ms),支持多种协议与格式,并具有丰富的功能特性,如多实例播放、事件回调、视频及音频格式支持等。此外,提供了基于Unity的播放器示例代码,展示了如何配置播放参数并开始播放。最后,作者指出此类技术在远程控制、虚拟仿真等应用场景中的重要意义。
|
4月前
|
编解码 开发工具 Android开发
Android平台RTSP|RTMP播放器如何实现TextureView渲染
本文介绍了在Android平台上使用TextureView进行RTSP和RTMP视频流渲染的技术背景和实现方法。TextureView相较于SurfaceView具备更高性能、更强功能性和更灵活的绘制方式等优势,但也有必须在硬件加速环境下运行和较高内存占用等局限。文中详细展示了如何在SmartPlayerV2工程中创建和配置TextureView,并通过代码示例解释了如何根据视频分辨率信息调整显示比例,以及处理TextureView的各种生命周期回调。此外,还列举了该播放器SDK支持的多项高级功能,如多实例播放、多种编码格式支持、硬解码能力等,旨在帮助开发者更好地理解和实现高性能的直播播放器。
|
4月前
|
编解码 监控 API
惊艳登场!揭秘如何在Android平台上轻松玩转GB28181标准,实现多视频通道接入的超实用指南!
【8月更文挑战第14天】GB28181是公共安全视频监控联网的技术标准。本文介绍如何在Android平台上实现该标准下的多视频通道接入。首先准备开发环境,接着引入GB28181 SDK依赖并初始化SDK。实现设备注册与登录后,通过指定不同通道号请求多路视频流。最后,处理接收到的数据并显示给用户。此过程涉及视频解码,需确保应用稳定及良好的用户体验。
101 0
|
4月前
|
编解码 网络协议 开发工具
Android平台RTSP|RTMP直播播放器技术接入说明
大牛直播SDK自2015年发布RTSP、RTMP直播播放模块,迭代从未停止,SmartPlayer功能强大、性能强劲、高稳定、超低延迟、超低资源占用。无需赘述,全自研内核,行业内一致认可的跨平台RTSP、RTMP直播播放器。本文以Android平台为例,介绍下如何集成RTSP、RTMP播放模块。
182 0
|
20天前
|
搜索推荐 前端开发 API
探索安卓开发中的自定义视图:打造个性化用户界面
在安卓应用开发的广阔天地中,自定义视图是一块神奇的画布,让开发者能够突破标准控件的限制,绘制出独一无二的用户界面。本文将带你走进自定义视图的世界,从基础概念到实战技巧,逐步揭示如何在安卓平台上创建和运用自定义视图来提升用户体验。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开新的视野,让你的应用在众多同质化产品中脱颖而出。
41 19