概述
**ContentProvider.java::openTypedAssetFile**
~~~
public AssetFileDescriptor openTypedAssetFile(Uriuri, String mimeTypeFilter,
Bundle opts) throws FileNotFoundException {
//本例满足下面的if条件
if("*/*".equals(mimeTypeFilter))
return openAssetFile(uri, "r");//此函数的代码见下文
StringbaseType = getType(uri);
if(baseType != null &&
ClipDescription.compareMimeTypes(baseType, mimeTypeFilter)) {
return openAssetFile(uri, "r");
}
throw newFileNotFoundException("Can't open " +
uri + " as type " + mimeTypeFilter);
}
~~~
**ContentProvider.java::openAssetFile**
~~~
public AssetFileDescriptor openAssetFile(Uri uri,String mode)
throws FileNotFoundException {
//openFile由子类实现。这里还以MediaProvider为例
ParcelFileDescriptor fd = openFile(uri, mode);
//根据openFile返回的fd得到一个AssetFileDescriptor对象
returnfd != null ? new AssetFileDescriptor(fd, 0, -1) : null;
}
~~~
下面分析MediaProvider实现的openFile函数。
1. MediaProvideropenFile分析
**MediaProvider.java::openFile**
~~~
public ParcelFileDescriptor openFile(Uri uri,String mode)
throws FileNotFoundException {
ParcelFileDescriptor pfd = null;
//假设URI符合下面的if条件,即客户端想读取的是某音乐文件所属专辑(Album)的信息
if(URI_MATCHER.match(uri) == AUDIO_ALBUMART_FILE_ID) {
DatabaseHelper database = getDatabaseForUri(uri);
......
SQLiteDatabase db = database.getReadableDatabase();
......
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
//得到客户端指定的代表该音乐文件的_id值
intsongid = Integer.parseInt(uri.getPathSegments().get(3));
qb.setTables("audio_meta");
qb.appendWhere("_id=" + songid);
Cursor c = qb.query(db,
new String [] {
MediaStore.Audio.Media.DATA,
MediaStore.Audio.Media.ALBUM_ID },
null, null, null, null, null);
if(c.moveToFirst()) {
String audiopath = c.getString(0);
//获取该音乐所属的album_id值
int albumid = c.getInt(1);
//注意,下面函数中调用的ALBUMART_URI将指向album_art表
Uri newUri = ContentUris.withAppendedId(ALBUMART_URI, albumid);
try {
//调用ContentProvider实现的openFileHelper函数。注意,pfd的
//类型是ParcelFileDescriptor
pfd = openFileHelper(newUri, mode);
} ......
}
c.close();
return pfd;
}
......
}
~~~
在以上代码中,MediaProvider将首先通过客户端指定的音乐文件的_id去查询它的专辑信息。此处给读者一个示例,如图7-8所示。
:-: ![](https://img-blog.csdn.net/20150803131007500?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
图7-8 audio_meta内容展示
图7-8中设置的SQL语句是select _id,album_id,_data from audio_meta,得到的结果集包含:第一列音乐文件的_id值,第二列返回音乐文件所属专辑的album_id值,第三列返回对应歌曲的文件存储路径。
以上代码在调用openFileHelper函数前构造了一个新的URI变量,根据代码中的注释可知,它将查询album_art表,不妨再看一个示例,如图7-9所示。
:-: ![](https://img-blog.csdn.net/20150803131023705?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
图7-9 album_art内容展示
在图7-9中,结果集的第一列为专辑艺术家的缩略图文件存储路径,第二列为专辑艺术家album_id值。所以,要打开的文件就是对应album_id的缩略图。再来看openFileHelper的代码。
2. ContentProvideropenFileHelper函数分析
**ContentProvider.java::openFileHelper**
~~~
protected final ParcelFileDescriptoropenFileHelper(Uri uri,
String mode) throws FileNotFoundException {
//获取缩略图的文件路径
Cursor c =query(uri, new String[]{"_data"}, null, null, null);
int count= (c != null) ? c.getCount() : 0;
if (count!= 1) {
......//一个album_id只能对应一个缩略图文件
}
c.moveToFirst();
int i =c.getColumnIndex("_data");
Stringpath = (i >= 0 ? c.getString(i) : null);
c.close();
if (path == null)
throw new FileNotFoundException("Column _data not found.");
intmodeBits = ContentResolver.modeToMode(uri, mode);
//创建ParcelFileDescriptor对象,内部会首先打开一个文件以得到
//一个FileDescriptor对象,然后再创建一个ParcelFileDescriptor对象,其实
//就是设置ParcelFileDescriptor中成员变量mFileDescriptor的值
returnParcelFileDescriptor.open(new File(path), modeBits);
}
~~~
至此,服务端已经打开指定文件了。那么,这个服务端的文件描述符是如何传递到客户端的呢?我们单起一节来回答这个问题。
最后
以上就是热情枕头为你收集整理的java setcontenprovider,7.6.2 ContentProvider的 openTypedAssetFile函数分析的全部内容,希望文章能够帮你解决java setcontenprovider,7.6.2 ContentProvider的 openTypedAssetFile函数分析所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复