Android 系统提供媒体库 URI 与 数据库的对应关系
2017-02-27 15:52
423 查看
Android 系统提供媒体库 URI 与 数据库的对应关系
前言
MediaProvider
queryUri uri
getDatabaseForUriuri
Uri
URI_MATCHERaddURI
URI_MATCHERmatchuri
总结
附MediaStore Uri 与 数据库对应表仅供参考
在使用
既然本地媒体文件在系统中是以
通过 Google 和 Baidu 找到了相关名词——
我想这个
从以上代码可以看出,在
在
URI是一个用于标识某一互联网资源名称的字符串。 该种标识允许用户对任何(包括本地和互联网)的资源通过特定的协议进行交互操作。在ContentProvider机制中,使用ContentResolver对象通过URI定位ContentProvider提供的资源。
ContentProvider使用的URI语法结构如下:
content:// 是通用前缀,表示该UIR用于ContentProvider定位资源。
< authority > 是授权者名称,用来确定具体由哪一个ContentProvider提供资源。因此一般< authority >都由类的小写全称组成,以保证唯一性。
< data_path > 是数据路径,用来确定请求的是哪个数据集。如果ContentProvider近提供一个数据集,数据路径则可以省略;如果ContentProvider提供多个数据集,数据路径必须指明具体数据集。数据集的数据路径可以写成多段格式,例如people/girl和people/boy。
< id > 是数据编号,用来唯一确定数据集中的一条记录,匹配数据集中_ID字段的值。如果请求的数据不只一条,< id >可以省略。
如请求整个people数据集的URI为:
而请求people数据集中第3条数据的URI则应写为:
添加
第二个参数
P. S.
Android中利用ContentResolver获取本地音乐和相片 ↩
Android ContentProvider 完全解析及简单DEMO ↩
MeidaProvider 源码(需梯子) ↩
Android ContentProvider 完全解析及简单DEMO ↩
UriMatcher | Android Developers ↩
前言
MediaProvider
queryUri uri
getDatabaseForUriuri
Uri
URI_MATCHERaddURI
URI_MATCHERmatchuri
总结
附MediaStore Uri 与 数据库对应表仅供参考
Android 系统提供媒体库 URI 与 数据库的对应关系
前言
在 Android 系统中,本地媒体(e.g. 音乐)文件会被检索并且以数据库的形式进行保存管理,在开发 Android 程序的时候,我们可以使用
ContentProvider设置
uri去获取相关的数据1。
在使用
ContentProvider组件的时候,通常的做法是继承父类
ContentProvider,然后重载父类中
inser()、
delete()、
update()、
query()等方法实现对数据的操作2。
既然本地媒体文件在系统中是以
数据库的形式来管理,并且提供了
uri供我们使用,那么我猜在系统内部应该是有个
***Provider的去实现对
数据库的操作。
通过 Google 和 Baidu 找到了相关名词——
MediaProvider,并且找到了源码3。
MediaProvider
public class MeidaProvider extends ContentProvider { private static final Uri MEDIA_URI = Uri.parse("content://media"); private static final Uri ALBUMART_URI = Uri.parse("content://media/external/audio/albumart"); ... }
我想这个
MeidaProvider.class也许会给我们想要的线索,因为使用
ContentResolver获取本地音乐中,使用的
uri为
content://media/external/audio/media,而这个
class也出现了类似的字段。
MeidaProvider extends ContentProvider那么应该会
重载 ContentProvider的相关方法以向外提供数据操作方法。而在查询音乐数据使用的方法为
query(Uri uri, ...)传入一个
uri,所以先查看
query( )的内容。
query(Uri uri, …)
//MediaProvider.class:1813 public Cursor query(Uri uri, String[] projectionIn, String selection, String[] selectionArgs, String sort) { int table = URI_MATCHER.match(uri); ... String groupBy = null; DatabaseHelper helper = getDatabaseForUri(uri); ... switch (table) { ... case AUDIO_MEDIA: if (projectionIn != null && projectionIn.length == 1 && selectionArgs == null && (selection == null || selection.equalsIgnoreCase("is_music=1") || selection.equalsIgnoreCase("is_podcast=1") ) && projectionIn[0].equalsIgnoreCase("count(*)") && keywords != null) { //Log.i("@@@@", "taking fast path for counting songs"); qb.setTables("audio_meta"); } else { qb.setTables("audio"); for (int i = 0; keywords != null && i < keywords.length; i++) { if (i > 0) { qb.appendWhere(" AND "); } qb.appendWhere(MediaStore.Audio.Media.ARTIST_KEY + "||" + MediaStore.Audio.Media.ALBUM_KEY + "||" + MediaStore.Audio.Media.TITLE_KEY + " LIKE ? ESCAPE '\\'"); prependArgs.add("%" + keywords[i] + "%"); } } break; case AUDIO_MEDIA_ID: qb.setTables("audio"); qb.appendWhere("_id=?"); prependArgs.add(uri.getPathSegments().get(3)); break; ... } //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); ... }
从以上代码可以看出,在
query( )中,使用
URI_MATCHER.match(uri)对传入的
uri进行解析,然后在
switch( )去
setTables( )设置对应的表或者视图。
getDatabaseForUri(uri);
//MediaProvider.java:4456 private DatabaseHelper getDatabaseForUri(Uri uri) { synchronized (mDatabases) { if (uri.getPathSegments().size() >= 1) { return mDatabases.get(uri.getPathSegments().get(0)); } } return null; } //MediaProvider.java:4490 private Uri attachVolume(String volume) { //将 “db” 路径判断存入 “mDatabases” }
在
MediaProvider.onCrearte()被创建启动的时候会查看是否有外置存储器,并执行
attachVolume()方法(:508),将内外置存储器中的数据库路径存入
mDatabases。
Uri
通用资源标识符(Uniform Resource Identifier)4URI是一个用于标识某一互联网资源名称的字符串。 该种标识允许用户对任何(包括本地和互联网)的资源通过特定的协议进行交互操作。在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/3
URI_MATCHER.addURI( );
Add 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预留位置,用于指明访问的数据库位于 内置存储器 或是 外置存储器 。
URI_MATCHER.match(uri);
源码使用了UriMatch对传入的
uri进行匹配。
总结
MediaProvider本质上就是一个
Provider,用过
ContentProvider去理解应该不难。
附:MediaStore Uri 与 数据库对应表(仅供参考)
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 |
MediaProvider.class比较大,下载下来之后,放到
Android Studio上可以方便查看代码。
Android中利用ContentResolver获取本地音乐和相片 ↩
Android ContentProvider 完全解析及简单DEMO ↩
MeidaProvider 源码(需梯子) ↩
Android ContentProvider 完全解析及简单DEMO ↩
UriMatcher | Android Developers ↩
相关文章推荐
- <1>Android 系统名字、版本、API level的对应关系
- Android系统源码数据库(mmssms.db)中几个表之间的关系
- Android 系统名字、版本、API level的对应关系
- Android中声音文件与数据库表的对应关系
- Android - 通过系统数据库获取SD卡音乐媒体信息
- 使用 android 系统提供的 app 打开对应文件
- 内容提供器访问Android数据库时候必须版本对应一致
- Android 系统名字、版本、API level的对应关系
- Android系统源码数据库(mmssms.db)中几个表之间的关系【转】
- Android系统源码数据库(mmssms.db)中几个表之间的关系.
- Android 系统名字、版本、API level的对应关系
- Android 系统名字、版本、API level的对应关系
- Android 系统名字、版本、API level的对应关系
- Android 系统的名字 及 版本和api基本对应关系 及 代码获取
- Android 系统名字、版本、API level的对应关系
- Android 系统名字、版本、API level的对应关系
- Android 系统名字、版本、API level的对应关系
- Android系统源码数据库(mmssms.db)中几个表之间的关系
- Android 系统名字、版本、API level的对应关系
- [Android Pro] 判断Uri对应的ContentProvider所操作的数据库u存在,及DownloadManager的暂停,继续