Android 系统提供媒体库 URI 与 数据库的对应关系前言MediaPRoviderqueryUri uri getDatabaseForUriuriUriURI_MATCHERaddURI URI_MATCHERmatchuri总结附MediaStore Uri 与 数据库对应表仅供参考
在 Android 系统中,本地媒体(e.g. 音乐)文件会被检索并且以 数据库
的形式进行保存管理,在开发 Android 程序的时候,我们可以使用 ContentProvider
设置 uri
去获取相关的数据1。 在使用 ContentProvider
组件的时候,通常的做法是继承父类 ContentProvider
,然后重载父类中 inser()
、 delete()
、 update()
、 query()
等方法实现对数据的操作2。 既然本地媒体文件在系统中是以 数据库
的形式来管理,并且提供了 uri
供我们使用,那么我猜在系统内部应该是有个 ***Provider
的去实现对 数据库
的操作。 通过 Google 和 Baidu 找到了相关名词——MediaProvider
,并且找到了源码3。
我想这个 MeidaProvider.class
也许会给我们想要的线索,因为使用 ContentResolver
获取本地音乐中,使用的 uri
为 content://media/external/audio/media
,而这个 class
也出现了类似的字段。 MeidaProvider extends ContentProvider
那么应该会 重载 ContentProvider
的相关方法以向外提供数据操作方法。而在查询音乐数据使用的方法为 query(Uri uri, ...)
传入一个 uri
,所以先查看 query( )
的内容。
从以上代码可以看出,在 query( )
中,使用 URI_MATCHER.match(uri)
对传入的 uri
进行解析,然后在 switch( )
去 setTables( )
设置对应的表或者视图。
在 MediaProvider.onCrearte()
被创建启动的时候会查看是否有外置存储器,并执行 attachVolume()
方法(:508),将内外置存储器中的数据库路径存入 mDatabases
。
通用资源标识符(Uniform Resource Identifier)4
URI是一个用于标识某一互联网资源名称的字符串。 该种标识允许用户对任何(包括本地和互联网)的资源通过特定的协议进行交互操作。在ContentProvider机制中,使用ContentResolver对象通过URI定位ContentProvider提供的资源。 ContentProvider使用的URI语法结构如下:
content://<authority>/<data_path>/<id> content:// 是通用前缀,表示该UIR用于ContentProvider定位资源。 < authority > 是授权者名称,用来确定具体由哪一个ContentProvider提供资源。因此一般< authority >都由类的小写全称组成,以保证唯一性。 < data_path > 是数据路径,用来确定请求的是哪个数据集。如果ContentProvider近提供一个数据集,数据路径则可以省略;如果ContentProvider提供多个数据集,数据路径必须指明具体数据集。数据集的数据路径可以写成多段格式,例如people/girl和people/boy。 < id > 是数据编号,用来唯一确定数据集中的一条记录,匹配数据集中_ID字段的值。如果请求的数据不只一条,< id >可以省略。如请求整个people数据集的URI为:
content://com.example.peopleprovider/people而请求people数据集中第3条数据的URI则应写为:
content://com.example.peopleprovider/people/3Add a URI to match, and the code to reutrn when this URI is matched. URI nodes may be exact match string, the token “*” that matches any text, or the token “#” that matches only numbers.5
//MediaProvider.class:4716 static { ... URI_MATCHER.addURI("media", "*/audio/media", AUDIO_MEDIA); URI_MATCHER.addURI("media", "*/audio/media/#", AUDIO_MEDIA_ID); URI_MATCHER.addURI("media", "*/audio/media/#/genres", AUDIO_MEDIA_ID_GENRES); ... }添加 uri
匹配对应关系。 第二个参数 "*/audio/media"
中的 “*” 给 internal
和 external
预留位置,用于指明访问的数据库位于 内置存储器 或是 外置存储器 。
源码使用了 UriMatch
对传入的 uri
进行匹配。
MediaProvider
本质上就是一个 Provider
,用过 ContentProvider
去理解应该不难。
URI (content://media/external/audio/) | Table / View (external.db) |
---|---|
media (specific) | audio_meta |
media (all) & media/# | audio |
media/#/genres & media/#/genres/# | audio_genres |
media/#/playlists & media/#/playlists/# | audio_playlists |
genres & genres/# | audio_genres |
genres/#/members | audio_genres_map_noid |
genres/all/members | audio_genres_map_noid |
playlists & playlists/# | audio_playlists |
playlists/#/members & playlists/#/members/# | audio_playlists_map |
artists (specific) | audio_meta |
artists (all) & artists/# | artist_info |
artists/#/albums | [多张表联合] |
albums (specific) | audio_meta |
albums (all) & albums/# | album_info |
albumart/# | album_art |
P. S. MediaProvider.class
比较大,下载下来之后,放到 Android Studio
上可以方便查看代码。
新闻热点
疑难解答