原文:http://blog.csdn.net/kallyena/article/details/7107070
http://blog.csdn.net/lgl125/article/details/7559124
http://hi.baidu.com/zlykeepon/item/6c5db3eec1f74f2c5b2d64dd
主要分为几节:
1. Android的媒体文件内部是如何存储的?
2. Andoid的媒体文件如何获取?
3. 在使用媒体文件的一些小技巧。
1. Android的多媒体如何存储的?
Android的多媒体文件主要存储在/data/data/com.android.providers.media/databases目录下,该目录下有两个db文件,一个是内部存储数据库文件(internal.db),一个是存储卡数据库(external-XXXX.db)。媒体文件的操作主要是围绕着这两个数据库来进行。这两个数据库的结构是完全一模一样的。
我们先看一下这两个数据库包含了哪些表。
album_art audio search
album_info audio_genres searchhelpertitle
albums audio_genres_map thumbnails
android_metadata audio_meta video
artist_info audio_playlists videothumbnails
artists audio_playlists_map
artists_albums_map images
先从基本的分析:
Images表:主要存储images信息。可以看一下这个表的结构:
CREATE TABLE images (_id INTEGERPRIMARY KEY,_data TEXT,_size INTEGER,_display_name TEXT,mime_type TEXT,title
TEXT,date_added INTEGER,date_modifiedINTEGER,description TEXT,picasa_id TEXT,isprivate INTEGER,latitude DOUBL
E,longitude DOUBLE,datetakenINTEGER,orientation INTEGER,mini_thumb_magic INTEGER,bucket_id TEXT,bucket_displa
y_name TEXT);
包含了一些基本信息,其中大家一看就明白了。
Thumbnails表:这个表和images表是有直接关系的。主要存储图片的缩略图,Android为每一张保存进系统的图片文件都会自动生成一张缩略图文件。关于这一点还有一些特殊的技巧后面再讲。我们可以看一下这个表的结构:
CREATE TABLE thumbnails (_id INTEGERPRIMARY KEY,_data TEXT,image_id INTEGER,kind INTEGER,width INTEGER,height INTEGER);
每一张image对应一条thumbnail记录。
Video表:主要存储视频信息了。和images表类似。表结构如下:
CREATE TABLE video (_id INTEGERPRIMARY KEY,_data TEXT NOT NULL,_display_name TEXT,_size INTEGER,mime_typeTEXT,date_added INTEGER,date_modified INTEGER,title TEXT,durationINTEGER,artist TEXT,album TEXT,resolution TEXT,description TEXT,isprivateINTEGER,tags TEXT,category TEXT,language TEXT,mini_thumb_data TEXT,latitudeDOUBLE,longitude DOUBLE,datetaken INTEGER,mini_thumb_magic INTEGER, bucket_idTEXT, bucket_display_name TEXT, bookmark INTEGER);
Videothumbnails表:存储视频的缩略图信息。这个和thumbnails表类似。
Audio表:音频信息比视频信息和图片信息要稍微复杂一些,主要是存储了一些专辑(album)、歌手(artists)信息,而专辑和歌手信息是单独的表格存储的,audio其实是一个视图,真正的音频数据信息存储在audio_meta表格中。我们可以看一下audio视图的定义:
CREATE VIEW audio as SELECT * FROMaudio_meta LEFT OUTER JOIN artists ON audio_meta.artist_id=artists.artist_idLEFT OUTER JOIN albums ON audio_meta.album_id=albums.album_id;
Albums表:主要存储专辑信息。
Artists表:主要存储歌手信息。不多赘述。
其他的一些表格我们平时可能用的比较少,就不做描述了,有兴趣可以自行研究一下。
2. Android的多媒体如何获取?
Android提供了媒体获取与存储的相关API,主要包含在android.provider.MediaStorepackage中。
MediaStore.Audio.AlbumColumns | Columns representing an album |
MediaStore.Audio.ArtistColumns | Columns representing an artist |
MediaStore.Audio.AudioColumns | Columns for audio file that show up in multiple tables. |
MediaStore.Audio.GenresColumns | Columns representing an audio genre |
MediaStore.Audio.PlaylistsColumns | Columns representing a playlist |
MediaStore.Files.FileColumns | Fields for master table for all media files. |
MediaStore.Images.ImageColumns |
|
MediaStore.MediaColumns | Common fields for most MediaProvider tables |
MediaStore.Video.VideoColumns |
|
MediaStore | The Media provider contains meta data for all available media on both internal and external storage devices. |
MediaStore.Audio | Container for all audio content. |
MediaStore.Audio.Albums | Contains artists for audio files |
MediaStore.Audio.Artists | Contains artists for audio files |
MediaStore.Audio.Artists.Albums | Sub-directory of each artist containing all albums on which a song by the artist appears. |
MediaStore.Audio.Genres | Contains all genres for audio files |
MediaStore.Audio.Genres.Members | Sub-directory of each genre containing all members. |
MediaStore.Audio.Media |
|
MediaStore.Audio.Playlists | Contains playlists for audio files |
MediaStore.Audio.Playlists.Members | Sub-directory of each playlist containing all members. |
MediaStore.Files | Media provider table containing an index of all files in the media storage, including non-media files. |
MediaStore.Images | Contains meta data for all available images. |
MediaStore.Images.Media |
|
MediaStore.Images.Thumbnails | This class allows developers to query and get two kinds of thumbnails: MINI_KIND: 512 x 384 thumbnail MICRO_KIND: 96 x 96 thumbnail |
MediaStore.Video |
|
MediaStore.Video.Media |
|
MediaStore.Video.Thumbnails | This class allows developers to query and get two kinds of thumbnails: MINI_KIND: 512 x 384 thumbnail MICRO_KIND: 96 x 96 thumbnail |
简单的观察一下,发现这些类也就是对数据库中的一些表的封装,弄懂了底层的存储结构,对于了解这些类的作用就很容易了。
Android系统中的每一种媒体文件有两种地址描述方式。
第一种模式,大家知道,在Android中,Content Provider是用来存储和获取公共数据的统一接口,Content Provider为每一类资源分配了URI地址,比如图片的地址就包括MediaStore.Images.Media.INTERNAL_CONTENT_URI和MediaStore.Images.Media.EXTERNAL_CONTENT_URI两个基础地址,其值分别是content://media/internal/images/media和content://media/external/images/media,对应内部库和外部库地址。每一张图片的地址基本上是上面的基础URL地址下加上图片的内部ID。打个比方一张存储卡上的图片ID为2,其对应的Uri地址就是content://media/external/images/media/2.知道了这个地址,基本上就可以操作这张图片的所有信息了。
另外一种描述文件地址标识就是传统的文件路径模式了,比如一张存储卡上的图片地址可能描述为:/mnt/sdcard/images/1.jpg。其实这个路径存储在images表格中的data字段中,有了这点关联,我们可以在这两种模式下进行任意切换。
前一种模式下,主要通过MediaStore.Images.Media、MediaStore.Audio.Media、MediaStore.Video.Media三个库中的query方法来查询或者获取特定条件的媒体了。
基本用法1:从一个Content Uri地址中生成Bitmap
可以采用android.provider.MediaStore.Images.Media.getBitmap(ContentResolver cr, Uri url)方法,其中ContentResolver是应用与资源之间的衔接人,它的示例通常可以通过在Activity中调用的getContentResolver()方法中获取。Uri地址就是上面描述的content://media/external/images/media/2类似地址,也就是Content Provider定义的地址形式。
基本用法2:从一个传统地址中生成Bitmap
有时候我们只知道一张图片的路径,并不知道图片的内部地址,想去获取该图片,可以采用android.graphics.BitmapFactory中的decodeXXX方法来搞定,比如decodeFile方法就是从文件路径中读取图片,原图片可以支持jpg,png,gif,bmp等各种格式。decodeByteArray就是从字节流中解码了。最后都是转换成Bitmap格式。
基本用法3:获取一张图片的缩略图
有时候我们需要显示图片的缩略图,可以采用android.provider.MediaStore.Images.Thumbnails的 getThumbnail方法。另外其实也可以采用bitmap的compress的方法对图片进行一些压缩处理。
Android系统提供了MediaScanner,MediaProvider,MediaStore等接口,并且提供了一套数据库表格,通过Content Provider的方式提供给用户。当手机开机或者有SD卡插拔等事件发生时,系统将会自动扫描SD卡和手机内存上的媒体文件,如audio,video,图片等,将相应的信息放到定义好的数据库表格中。在这个程序中,我们不需要关心如何去扫描手机中的文件,只要了解如何查询和使用这些信息就可以了。MediaStore中定义了一系列的数据表格,通过ContentResolver提供的查询接口,我们可以得到各种需要的信息。下面我们重点介绍查询SD卡上的音乐文件信息。
先来了解一下ContentResolver的查询接口:
Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder);
Uri:指明要查询的数据库名称加上表的名称,从MediaStore中我们可以找到相应信息的参数,具体请参考开发文档。
Projection: 指定查询数据库表中的哪几列,返回的游标中将包括相应的信息。Null则返回所有信息。
selection: 指定查询条件
selectionArgs:参数selection里有 ?这个符号是,这里可以以实际值代替这个问号。如果selection这个没有?的话,那么这个String数组可以为null。
SortOrder:指定查询结果的排列顺序
下面的命令将返回所有在外部存储卡上的音乐文件的信息:
Cursor cursor = query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
得到cursor后,我们可以调用Cursor的相关方法具体的音乐信息:
歌曲ID:MediaStore.Audio.Media._ID
Int id = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media._ID));
String tilte = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE));
歌曲的专辑名:MediaStore.Audio.Media.ALBUM
String album = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM));
歌曲的歌手名: MediaStore.Audio.Media.ARTIST
String artist = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST));
歌曲文件的全路径 :MediaStore.Audio.Media.DATA
String url = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA));
歌曲文件的名称:MediaStroe.Audio.Media.DISPLAY_NAME
String display_name = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DISPLAY_NAME));
歌曲文件的发行日期:MediaStore.Audio.Media.YEAR
String year = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.YEAR));
Int duration = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DURATION));
歌曲文件的大小 :MediaStore.Audio.Media.SIZE
Int size = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.SIZE));
MediaStore 与Media.EXTERNAL_CONTENT_URI
MediaStore这个类是android系统提供的一个多媒体数据库,android中多媒体信息都可以从这里提取。这个MediaStore包括了多媒体数据库的所有信息,包括音频,视频和图像,android把所有的多媒体数据库接口进行了封装,所有的数据库不用自己进行创建,直接调用利用ContentResolver去掉用那些封装好的接口就可以进行数据库的操作了。今天我就介绍一些这些接口的用法。 首先,要得到一个ContentResolver实例,ContentResolver可以这样获取,利用一个Activity或者Service的Context即可。如下所示:ContentResolver mResolver = ctx.getContentResolver();
上面的那个ctx的就是一个context,Activity.this就是那个Context,这个Context就相当于一个上下文环境。得到这个Context后就可以调用getContentResolver接口获取ContentResolver实例了。ContentResolver实例获得后,就可以进行各种查询,下面我就以音频数据库为例讲解增删改查的方法,视频和图像和音频非常类似。
在讲解各种查询之前,我给大家介绍下怎么看android都提供了哪些多媒体表。在adbshell中,找到/data/data/com.android.providers.media/databases/下,然后找到SD卡的数据库文件(一般是一个.db文件),然后输入命令sqlite3加上这个数据库的名字就可以查询android的多媒体数据库了。.table命令可以列出所有多媒体数据库的表,.scheme加上表名可以查询表中的所有列名。这里可以利用SQL语句来查看你想要的数据,记得最后一定要记住每条语句后面都加上分号。下面开始讲述怎么在这些表上进行增删改查。
查询,代码如下所示:
Cursor cursor = resolver.query(_uri, prjs, selections, selectArgs, order);
ContentResolver的query方法接受几个参数,参数意义如下:
Uri:这个Uri代表要查询的数据库名称加上表的名称。这个Uri一般都直接从MediaStore里取得,例如我要取所有歌的信息,就必须利用MediaStore.Audio.Media. EXTERNAL_CONTENT_URI这个Uri。专辑信息要利用MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI这个Uri来查询,其他查询也都类似。
Prjs:这个参数代表要从表中选择的列,用一个String数组来表示。
Selections:相当于SQL语句中的where子句,就是代表你的查询条件。
selectArgs:这个参数是说你的Selections里有?这个符号是,这里可以以实际值代替这个问号。如果Selections这个没有?的话,那么这个String数组可以为null。
Order:说明查询结果按什么来排序。
上面就是各个参数的意义,它返回的查询结果一个Cursor,这个Cursor就相当于数据库查询的中Result,用法和它差不多。
-------------------------------------------------------------------------------------------------------------------
增加,代码如下所以:
ContentValues values = new ContentValues();
values.put(MediaStore.Audio.Playlists.Members.PLAY_ORDER,0);
resolver.insert(_uri, values);
这个insert传递的参数只有两个,一个是Uri(同查询那个Uri),另一个是ContentValues。这个ContentValuses对应于数据库的一行数据,只要用put方法把每个列的设置好之后,直接利用insert方法去插入就好了。
更新,代码如下:
ContentResolver resolver = ctx.getContentResolver();
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
ContentValues values = new ContentValues();
values.put(MediaStore.Audio.Media.DATE_MODIFIED, sid);
resolver.update(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,values, where, selectionArgs);
上面update方法和查询还有增加里的参数都很类似,这里就不再重复叙述了,大家也可直接参考google的文档,那里也写的很清楚。
删除,代码如下:
ContentResolver resolver = ctx.getContentResolver();
nbsp; resolver.delete(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,where, selectionArgs);
delete和更新的方法很类似,大家对照更新的方法看下马上就会明白。