[重要]使用Vitamio打造自己的Android万能播放器(10)—— 本地播放 (缩略图、视频信息、视频扫描服务)
注意
本章ContentProvider在2012-8-31发布的SDK中已经不能使用,后续文章会更新用法。
欢迎转载,但请保留文章原始出处:) 博客园:http://www.cnblogs.com 农民伯伯: http://over140.cnblogs.com
4、使用Vitamio打造自己的Android万能播放器(4)——本地播放(快捷搜索、数据存储)
5、使用Vitamio打造自己的Android万能播放器(5)——在线播放(播放优酷视频)
6、使用Vitamio打造自己的Android万能播放器(6)——在线播放(播放列表)7、使用Vitamio打造自己的Android万能播放器(7)——在线播放(下载视频)
8、使用Vitamio打造自己的Android万能播放器(8)——细节优化
9、使用Vitamio打造自己的Android万能播放器(9)—— 在线播放 (在线电视)
正文
一、目标
1.1 获取视频缩略图等
之前的文章都是自己扫描获取的视频文件信息,这里补充获取视频缩略图、视频宽带的代码,参加文章2.1部分。
1.2 调用Vitamio的扫描服务
新版SDK已经内置了视频扫描服务,提供了本地视频播放所需的全部数据。
二、实现
2.1 自己扫描获取视频的缩略图、视频宽高
![复制代码](http://common.cnblogs.com/images/copycode.gif)
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;
![复制代码](http://common.cnblogs.com/images/copycode.gif)
}
代码说明:
a). 缩略图的尺寸是可以调整的,大家可以看一下这个默认大小。
b). 这里的代码是缩略图默认存在当前视频路径下面,并且文件名和视频名称一样,多加了一个jpg的后缀。
2.2 调用Vitamio的视频扫描服务
2.2.1 AndroidManifest.xml
![复制代码](http://common.cnblogs.com/images/copycode.gif)
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
![复制代码](http://common.cnblogs.com/images/copycode.gif)
代码说明:
主要是MediaScannerService服务和MediaScannerReceiver监听器的注册。
2.2.2 启动扫描服务(MainFragmentActivity)
![复制代码](http://common.cnblogs.com/images/copycode.gif)
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);
}
![复制代码](http://common.cnblogs.com/images/copycode.gif)
代码说明:
OPreference对象封装了SharedPreferences 存储数据。这里判断了是否首次启动应用,是的话启动视频扫描服务。
2.2.3 获取数据(FragmentFile)
![复制代码](http://common.cnblogs.com/images/copycode.gif)
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, null, null, 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);
}
![复制代码](http://common.cnblogs.com/images/copycode.gif)
代码说明:
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
相关文章
- 加密狗android,Android系统加密狗的设计与实现
- Android listview 实现列表多选
- android sdk根目录,Android SDK位置
- android短信验证码代码,Android短信验证码自动填写实现代码
- Android前台服务的使用(二)--使用LiveEventBus实现进程间通讯(附源码)
- android toast 自定义时间,Android 自定义 Toast 显示时间「建议收藏」
- Android学习(简单使用Bottom Navigation Activity来实现底部导航栏)
- android sqlite 判断表和表中字段是否存在方法
- 【Android Gradle 插件】build.gradle 中的 android 配置 ( 配置项 | compileSdkVersion 配置 | buildToolsVersion 配置 )
- 【错误记录】Android 应用安装后出现两个启动图标 ( 排查应用及依赖库中配置了 android.intent.category.LAUNCHER 的 Activity )
- 【Android FFMPEG 开发】Android 中执行 FFMPEG 指令 ( 集成 mobile-ffmpeg 框架 | 完整代码示例 )
- 【Android Gradle 插件】自定义 Gradle 任务 ⑭ ( TaskOutputs#upToDateWhen 设置重复任务是否执行 | Gradle 预置任务 )
- 【Android 逆向】ART 函数抽取加壳 ⑤ ( unistd.h#execve 函数分析 | 使用自定义的 myexecve 函数替换 libc.so#execve 函数 )
- android EventBus详解(二)手机开发
- 深入理解Android IPC机制之Binder机制详解手机开发
- 亚马逊带广告的IMDb TV服务终于推出了Android和iOS应用
- 使用Android实现连接MySQL数据库:实现快速数据交互与管理(android连接mysql数据库)
- Android 开发必备知识:我和 Gradle 有个约会
- Android界面刷新的方法分享
- Android利用方向传感器实现指南针具体步骤
- Android中的android:layout_weight使用详解
- Android放大镜的实现代码
- Android实现GPS定位代码实例
- Android中引用其他程序的文本资源超简单方法
- Android入门之AlertDialog用法实例分析