最近都在研究android4.0的gallery,深感复杂,写下文档,先贴着一部分先。欢迎大家看后交流,乐意接受批评指正。
1.1.1 进入gallery
进行如下关键操作。
l 先进入gallery’中处理。Gallery中initializeByIntent中最终会调用启动albumset,代码如下。
Bundledata = new Bundle();
data.putString(AlbumSetPage.KEY_MEDIA_PATH,
getDataManager().getTopSetPath(DataManager.INCLUDE_ALL));
getStateManager().startState(AlbumSetPage.class, data);
l 初始化view,创建albumsetview并注册其侦听者,该侦听者负责侦听用户点击触摸操作。
l 创建GLView类的对象,在该对象重载实现onlayout()以及render函数。其中onlayout()在每次进入这个主界面时调用,render()在每次该界面视图改变时调用,例如触摸等操作使得界面视图改变调用render来重绘。
l 创建界面上的其他元素。
l 创建过渡动画。
1.1.2 退出gallery
l 调用onbackpressed退出。
l 最终执行退出操作是由StateManager的finishState。该函数会先出栈一个activitystate,后再判断是否栈为空,为空才真正终止应用退出。
1.1.3 打开相册
在点击进入相册前进行如下操作。
l 若进入的相册下一级已经没有相册了,那就启动albumpage。
l 若进入的相册下一级仍有相册了,那就启动albumsetpage。
进入albumpage后,主要步骤跟进入gallery时差不多。
1.1.4 打开相片或视频
1)打开图片见3.1.5。
2)打开视频见下面分析。主要操作见下面。
l ControllerOverlay用于播放控件的实现,诸如时间条,屏幕中间显示的播放状态按钮等等。
l 加载各种view,控件。
l Movieplayer中的Bookmarker是个书签功能,看代码就是负责保存本次播放的位置,等挂起后重新进入gallery可以从上一次播放位置继续播放。
1.1.5 播放幻灯片
主要操作如下。
l 初始化数据以及view。
l 指定播放幻灯片按什么顺序播放,或是随机,或是顺序。
1.1.6 删除图片或视频
主要操作如下。
l 删除操作在三个地方有,gallery主界面、相册内界面、图片浏览界面,他们都是由界面上方的actionbar按钮触发。
l Albumsetpage、albumpage均是创建ActionModeHandler来实现加载这个actionbar。Photopage是通过创建MenuExecutor来加载这个actionbar。另外这个actionbar同时包括actiobar的其他操作,诸如裁剪、编辑等等。
l 最终的删除操作是通过获取mediaobject对象,对其进行操作实现的。Mediaobject同时是mediaset、mediaitem的父类,多态性就能保证对相册或是相片进行删除操作。删除操作最终通过conresolver.delete实现。
1.1.7 开机与media相关的数据库流程
流程见下。
l 创建mediaprovider。Mediaprovider中oncreate主要做如下处理。
n 挂载内部存储器,创建内部存储器的数据库。
n 创建侦听者来侦听卸载存储器的事件,包括卸载内部存储器以及外部存储器。
n 挂载外部存储器,创建外部存储器的数据库。
n 创建线程,用于处理更新缩略图的请求。缩略图请求分为两种,一种是图片缩略图,处理原则是FIFO,先请求先处理;另一种是音乐专辑缩略图,处理原则是LIFO,后请求先处理。
l 与2.3一样,先通过mediascanerreceiver接收到Intent.ACTION_MEDIA_MOUNTED这个加载intent,调用scan对全盘媒体文件进行扫描。
l 接着调用到mediascannerservice。ServiceHandler中对指定路径进行扫描。调用到mediascannerservice.scan()。扫描前发送Intent.ACTION_MEDIA_SCANNER_STARTED广播,接着创建mediascanner进行扫描,扫描后发送Intent.ACTION_MEDIA_SCANNER_FINISHED。接收这两个广播的地方找不到。应该是用于提示外部的应用扫描的开始以及结束。
l 在扫描前会插入数据库一条记录,之后就删除该条记录。为什么要在之前插入一条记录,之后就删除这条记录,并且只是获取了uri,并没对这个uri进行操作,看不懂。代码如下。
UriscanUri = getContentResolver().insert(MediaStore.getMediaScannerUri(), values);
//...
getContentResolver().delete(scanUri,null, null);
调用mediascanner.scanDirectories扫描所有目录。
mediascanner.scanDirectories中,有如下关键操作。
n Initalize():初始化各个媒体uri。总共有如下uri。
mAudioUri
mVideoUri
mImagesUri
mThumbsUri
mFilesUri
n Prescan():扫描mFilesUri所示的文件。写入filecache中。同时计算mImagesUri的文件数。
n processDirectory():遍历扫描所有路径。具体进入c++代码,看不懂。
n Postscan():删除掉文件系统中不存在但数据库中存在的文件项,此删除为删除数据库中记录项。
1.1.8 Filemanager中删除媒体文件
删除单个文件主要流程见下。
在Filemanager中,主要操作流程如下。
l 删除该文件。
l FileMgrMenuUtil.notifyFileSystemChanged中发送Intent.ACTION_MEDIA_SCANNER_SCAN_FILE通知删除文件成功。Mediareceiver接收到就交给mediascannerservice进行scanfile()处理。
n Mediascannerservice.scanfile(),最终调用到Mediascanner.scansinglefile()处理。主要进行如下处理。
n 初始化各种扫描需要的东西,如路径等。
n Prescan():更新媒体文件的filecache。Filecache是一个索引表,存放媒体文件的关键数据,以提高访问这些文件的速度。
n Doscanfile():在这里主要是置标志位表示已经在文件系统找到该文件。
l 均是调用mediaobject.delete()完成删除操作,其实最终调用的是mediaobject派生出的mediaset、mediaitem。而跟进代码最终是在mediaprovider.delete处理。
l Mediaprovider.delete()主要是删除数据库中该条记录。
在Gallery中,主要需要注意流程如下。
l 均是调用mediaobject.delete()完成删除操作,其实最终调用的是mediaobject派生出的mediaset、mediaitem。而跟进代码最终是在mediaprovider.delete处理。
l Mediaprovider.delete()主要是删除数据库中该条记录。
l 但是不能找到地方处理删除文件操作。
删除目录。
在filemanager中,流程稍有不同,主要见以下。
l 会调用到RecursiveDeleteTask线程进行递归删除目录下文件的处理。
l FileMgrMenuUtil.notifyFileSystemChanged中发送Intent.ACTION_MEDIA_MOUNTED通知删除文件夹成功。Mediascannerservice进行scan()处理。其主要操作跟“开机与media相关的数据库流程”内的Mediascannerservice.scan()大同小异,区别在与扫描范围的不同。
在gallery中,操作见上面的删除单个文件操作。
1.1.9 Filemanager中移动媒体文件
移动单个文件。
在filemanager中,主要注意以下。
l 交由MoveTask线程处理,线程中通过file.renameto()来实现将文件移动到另一个地方,这个方法只是更改了原来文件路径。
l FileMgrMenuUtil.notifyFileSystemChanged中发送Intent.ACTION_MEDIA_SCANNER_SCAN_FILE通知移动文件成功。接着Mediascannerservice同样进行单个文件扫描处理。
移动一整个目录。
在filemanager中,主要注意以下。
l 主要通过以下数据结构来存放待处理的文件列表。
private ArrayList<FileInfo>mCheckedFileList = new ArrayList<FileInfo>();
l 同样还是MoveTask线程处理这些文件。
l FileMgrMenuUtil.notifyFileSystemChanged中发送Intent.ACTION_MEDIA_MOUNTED通知移动文件夹成功。Mediascannerservice进行scan()处理。
1.1.10 Filemanager中重命名媒体文件
重命名单个文件与文件夹操作基本一致。
Filemanager中,主要操作流程如下。
l 同样使用file.renameto()进行重命名文件操作。
l 同样使用FileMgrMenuUtil.notifyFileSystemChanged发送intent消息通知重命名操作,使得Mediascannerservice再去扫描。这里发送的intent消息,重命名单个文件与重命名文件夹是不一样的,与之前区别一样。
1.1.11 Filemanager中复制媒体文件
复制单个文件。
在filemanager中,主要操作流程如下。
l 检查目的地址空间足够与否。
l 同样使用FileMgrMenuUtil.notifyFileSystemChanged发送intent消息通知重命名操作,使得Mediascannerservice再去扫描。这里发送的intent消息,重命名单个文件与重命名文件夹是不一样的,与之前区别一样。
复制目录。与单个文件操作基本一致。主要见以下。
l 递归实现copy。
1.1.12 增加媒体文件
在camera拍摄一张照片后,主要进行如下操作。
l 生成这个jpeg格式的图片。
l ContentResolver中插入一条关于这照片的记录到对应数据库中。