引言
VLC(Video LAN Client)是一款开源软件,其安装简单且运行稳定,支持多种平台(包括 Windows、Linux、Mac、Unix)。VLC Media Player 媒体播放器是为多媒体播放而服务的软件,系统占用率非常低,支持大多数的主流音视频格式,如 MPEG、WMV、MP4、MOV、3GP、FLV (Flash) 等。既可播放 DVD 影碟,又支持在线媒体播放。
目前VLC已完全支持中文,被国内用户广泛使用,也被越来越多Android平台爱好者所关注[1]。在智慧校园和数字化校园的建设中,随着多媒体通信的不断应用,在网络教学和远程教育过程中应用移植和扩展VLC源码的方案越来越多[2]。本项目是开发一款基于Android平台的学习资源视频点播平台,以扩展远程教育中对移动学习的支持方式。通过对VLC源码深入分析和核心模块移植而进行二次开发,利用其良好的多媒体格式支持库和UI框架,大大加快了项目的开发进度。
1 Android平台依赖库编译
由于VLC的跨平台性,在多个平台下都可成功编译和移植,本次项目讨论在Ubuntu 12.10环境下的VLC库生成过程。首先系统环境需要安装ant、gawk、libtool、m4、patch、pkgconfig、ragel等工具,使用“aptget builddep vlc”命令安装VLC相关依赖库,完成后安装JDK、Android SDK、NDK,并在/etc/profile中设置相应的环境变量和CPU类型,最后使用“sh compile.sh”命令开始编译。成功后在vlcandroid/libs/armeabi目录下生成libiomxgingerbread.so、libiomxhc.so、libiomxics.so和libvlcjni.so四个动态库。需要注意的是,尽量保证Ubuntu系统版本和JDK、SDK、NDK版本为最新,编译过程如遇无法下载依赖文件导致终止,则手动下载该文件后存放到android/vlc/contrib/tarballs/目录下。
当VLC的Android工程在eclipse中编译时,需要同时导入ActionBarSherlock、SlidingMenu和WheelView三个依赖库的工程,并在主工程属性中设置正确的依赖库路径。如出现无法生成目标版本的apk文件错误,有可能是由于SDK版本与VLC工程文件中目标版本不符,需要修改androidvlc目录下project.properties文件中的target值。
2 源码实现分析
从UI设计模式和底层数据库操作两个方面对Android平台上的VLC播放器实现机制进行分析。在编译过程中可以发现,整个VLC工程除了C代码与播放相关的编解码库之外,还有3个与UI设计紧密相关的依赖工程。
2.1 UI设计分析
VLC在Android终端上的运行界面(如图1所示)非常简洁、美观、易于操作,主要由操作栏、侧边导航、主框架构成。
图1 VLC主操作界面
操作栏(Action bar)是Android用户界面中最经典的用户界面设计模式之一[3],位于用户界面视图中的顶栏(如图1中标识1),左边由应用图标和上下文形式的操作按钮组成,右边包含了一个溢出菜单。在Android 3.0 Honeycomb版本的SDK中添加了对操作栏的支持,在4.0版本中加入了对手机操作栏的支持。这里使用了第三方开源库ActionBarSherlock,能够支持Android旧版本。
具体实现在prepareActionBar()函数里,先调用setNavigationMode()接口设置操作栏的风格,支持标准、列表和标签3种模式,这里先设置NAVIGATION_MODE_STANDARD值为标准模式,再调用setDisplayOptions(0,ActionBar.DISPLAY_SHOW_TITLE)接口显示标题,最后调用setDisplayHomeAsUpEnabled(true)显示Up按钮。当然,ActionBarSherlock还提供很多其他的设置以支持更复杂和个性化的设计,这里只描述与本项目相关的。对于Android 3.0之后的版本,应用启动时,如果附带操作栏会在view创建完成后调用onCreateOptionsMenu()来对Option Memu进行布局。这里的布局文件是R.menu.media_library,菜单项包括搜索、刷新等。需要注意的是,showAsAction属性值ifRoom能够让菜单根据操作栏右侧的空间来响应式布局,根据屏幕尺寸动态调整显示菜单项个数。
整个主框架分为左边导航和右边内容显示,该布局为一个全屏的FrameLayout。图1中标识2部分是侧边导航面板,与仪表盘设计模式相比,提供了对媒体文件更直接的分类访问。通过轻击操作栏上的Up按键或者边缘滑动手势打开侧边导航面板。这里使用了开源库SlidingMenu项目实现,导航通过mMenu.setBehindOffset()接口设置导航面板尺寸,为导航项设置容器,封装到listview中,在SidebarAdapter类中可看到放入了Video、Audio等4个选择项。右边内容显示部分由R.layout.main布局,使用帧布局来局部刷新显示内容,定义了一个专用的帧框架作为片段的占位符,其ID为fragment_placeholder。最后通过SlidingMenu的接口setMenu(sidebar)和setContent(main)来呈现。
主框架的内容显示就是图1中标识3部分,在导航的listview中注册了点击监听器OnItemClickListener(),其实现右侧内容显示流程如图2所示。
图2 主框架内容显示流程
内容显示使用了片段(fragment)来制作响应式用户界面。根据用户点击的导航项获取不同的ID标识,在连续2次轻击过程中,多媒体文件有可能做了添加或删除操作,所以需要把activity后退栈中的片段清空,然后根据ID号提交对应的片段来添加、删除或替换。实现这些操作需要定义一个FramentManager实例,并能支持事务更改片段,这里只做了replace()操作。正是因为构建了活动与片段交互的方法,才使多媒体文件的浏览过程具有了很大的灵活性。
2.2 多媒体文件的数据库管理
Android系统自带关系型数据库SQLite,能轻松实现管理本地存储的多媒体文件,包括音频和视频文件类型。VLC实现文件管理的功能包括按文件类型(音频或视频)、存储目录或者搜索过的历史记录来分别展现和管理,其功能实现的源文件主要包括MediaLibrary.java、MediaDatabase.java。
数据库操作类DatabaseHelper继承SQLiteOpenHelper辅助类来管理数据库的创建和版本,实现对数据库进行一些操作[4]。vlc_database数据库创建的表包括媒体文件信息表Media_table、存放路径表directories_table、播放排列表playlist_table、playlist_media_table和历史查找表searchhistory_table五个表,与媒体文件信息相关的Media_table表内容非常关键,各字段和数据类型如表1所列。
表1 Media_table表信息
利用adb调试程序可查看模拟器中数据库的实际信息,如Media_table表中存储的一条信息格式如下:
file:///mnt/sdcard/When%20You%20Believe.mp3|0|276148|1||WhenYou Believe|Mariah Carey |R&b|Mariah Carey Story|0|0||1|2
媒体文件的信息获取由Media类来实现,通过调用libVLC.readTracksInfo(mLocation)接口把文件信息保存到TrackInfo类中。系统启动时会在目录/media/、/Android/data/和外部存储SD卡上查找后缀是音频或视频的文件,读取信息并保存到表Media_table中。libVLC类是底层VLC库提供的播放接口,里面的方法是通过native关键字定义。
这正是利用VLC库来开发Android上播放器的优点,JNI是双向接口,不仅可以通过JNI在Java代码中访问Native模块,还可以在 Native代码中嵌入一个JVM,并通过JNI访问运行于其中的Java模块,实现了Java代码与Native代码的互访,提高了多媒体文件解码和定位的效率。
基于5张表中的信息,上层可以实现按文件类型(音频或视频)检索、按存储目录检索、按历史搜索行为检索等,而且在音频文件类型展示中还可以应用表中字段(如ARTIST,ALBUM,TITLE,GENRE)按类型对所有文件进行分门别类,还可以选择按名字或长度进行排序,提供了良好的操作体验。
系统查找所有媒体文件的具体实现在MediaLiarary类中,定义了内部类GetMediaItemsRunnable开启独立线程,主要操作directories_table、media_table两个表,实现流程如图3所示。
图3 多媒体文件搜索流程
结语
本项目通过分析源代码,从依赖库编译、UI设计和数据库管理的文件表单设计等方面入手,理清了代码组织结构、设计思路和实现机制,对后续的VLC跨平台移植和移动学习平台的视频点播系统开发具有很好的借鉴作用。设计中需要考虑以下几点:界面设计以易用性为重要品质,构建心智模型,并以用户为中心;恰当应用第三方开源库;使用片段实现响应式用户界面等。