Android的ContentResolver中有一个接口叫openAssetFileDescriptor,在doc中的解释如下:
public final openAssetFileDescriptor ( uri, mode)Since: API Level 3Open a raw file descriptor to access data under a URI. This interacts with the underlying method of the provider associated with the given URI, to retrieve any file stored there.
Accepts the following URI schemes:- content (SCHEME_CONTENT)
- android.resource (SCHEME_ANDROID_RESOURCE)
- file (SCHEME_FILE)
A Uri object can be used to reference a resource in an APK file. The Uri should be one of the following formats:
- android.resource://package_name/id_number
package_name is your package name as listed in your AndroidManifest.xml. For examplecom.example.myapp
id_number is the int form of the ID.
The easiest way to construct this form isUri uri =Uri.parse("android.resource://com.example.myapp/"+ R.raw.my_resource"); - android.resource://package_name/type/name
package_name is your package name as listed in your AndroidManifest.xml. For examplecom.example.myapp
type is the string form of the resource type. For example, raw or drawable. name is the string form of the resource name. That is, whatever the file name was in your res directory, without the type extension. The easiest way to construct this form isUri uri =Uri.parse("android.resource://com.example.myapp/raw/my_resource");
该接口返回AssetFileDescriptor,可以像读文件一样操作读取该uri的内容。
对应的ContentProvider必须实现openAssetFile接口,可以参考Android联系人中ContactsProvider2.java的实现:
ContactsProvider中将数据库中查询到的Photo blob数据,封装成一个MemoryFile,然后将该MemoryFile封装为
AssetFileDescriptor返回。
@Override
public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException {
int match = sUriMatcher.match(uri);
switch (match) {
case CONTACTS_PHOTO: {
return openPhotoAssetFile(uri, mode,
Data._ID + "=" + Contacts.PHOTO_ID + " AND " + RawContacts.CONTACT_ID + "=?"
,
new String[]{uri.getPathSegments().get(1)});
}
……
private AssetFileDescriptor openPhotoAssetFile(Uri uri, String mode, String selection,
String[] selectionArgs)
throws FileNotFoundException {
if (!"r".equals(mode)) {
throw new FileNotFoundException(mDbHelper.exceptionMessage("Mode " + mode
+ " not supported.", uri));
}
String sql =
"SELECT " + Photo.PHOTO + " FROM " + mDbHelper.getDataView() +
" WHERE " + selection;
SQLiteDatabase db = mDbHelper.getReadableDatabase();
return SQLiteContentHelper.getBlobColumnAsAssetFile(db, sql,
selectionArgs);
}
public static AssetFileDescriptor getBlobColumnAsAssetFile(SQLiteDatabase db, String sql,
String[] selectionArgs) throws FileNotFoundException {
try {
MemoryFile file = simpleQueryForBlobMemoryFile(db, sql, selectionArgs);
if (file == null) {
throw new FileNotFoundException("No results.");
}
return AssetFileDescriptor.fromMemoryFile(file);
} catch (IOException ex) {
throw new FileNotFoundException(ex.toString());
}
}
private static MemoryFile simpleQueryForBlobMemoryFile(SQLiteDatabase db, String sql,
String[] selectionArgs) throws IOException {
Cursor cursor = db.rawQuery(sql, selectionArgs);
if (cursor == null) {
return null;
}
try {
if (!cursor.moveToFirst()) {
return null;
}
byte[] bytes = cursor.getBlob(0);
if (bytes == null) {
return null;
}
MemoryFile file = new MemoryFile(null, bytes.length);
file.writeBytes(bytes, 0, 0, bytes.length);
file.deactivate();
return file;
} finally {
cursor.close();
}
}