Android为 Camera,Audio,Video等媒体文件提供MediaProvider用于数据的保存,删除,检索等。MediaProvider实现了 ContentProvider类的几个操作SQL的重要方法如insert ,delete, updata, query。MediaProvider中DatabaseHelper类用于获取与创建Database。
private static final class DatabaseHelper extends SQLiteOpenHelper {
final Context mContext;
final boolean mInternal; // True if this is the internal database
// In memory caches of artist and album data.
HashMap<String, Long> mArtistCache = new HashMap<String, Long>();
HashMap<String, Long> mAlbumCache = new HashMap<String, Long>();
public DatabaseHelper (Context context, String name, boolean internal) {
super(context, name, null, DATABASE_VERSION);
mContext = context;
mInternal = internal;
}
/**
* Creates database the first time we try to open it.
*/
@Override // 第一次打开数据库时创建Table
public void onCreate (final SQLiteDatabase db) {
updateDatabase(db, mInternal, 0, DATABASE_VERSION);
}
以Camera的image文件文件为例,数据库在第一次使用的时候 被创建,对于image文件,SQL在updateDatabase为其创建一个table:
db.execSQL ("CREATE TABLE IF NOT EXISTS images (" +
"_id INTEGER PRIMARY KEY," + //文件保存的序号
"_data TEXT," + //记录image 文件保存路径
"_size INTEGER," + //文件大小
"_display_name TEXT," + //图片名称
"mime_type TEXT," + //文件类型
"title TEXT," +
"date_added INTEGER," +
"date_modified INTEGER," +
"description TEXT," +
"picasa_id TEXT," +
"isprivate INTEGER," +
"latitude DOUBLE," +
"longitude DOUBLE," +
"datetaken INTEGER," +
"orientation INTEGER," +
"mini_thumb_magic INTEGER," +
"bucket_id TEXT," +
"bucket_display_name TEXT" +
");");
添加URI到match这个也很重要,因为不同类型的文件会保存在不同的table中,如果我们得到一个URI为: content://media/external/images/media/1 通过UriMatcher.match(uri)将返回注册的IMAGES_MEDIA_ID 值。
URI_MATCHER.addURI("media", "*/images/media", IMAGES_MEDIA );
URI_MATCHER.addURI("media", "*/images/media/#", IMAGES_MEDIA_ID );
URI格式解析如下:
URI格式中最重要的字段是authority,authority确定了操作数据库的Provider是由谁提供的。MediaProvider在AndroidManifest.xml中添加如下语句:
<provider android:name="MediaProvider " android:authorities=" media "
android:multiprocess="false" />
Provider加载
MediaProvider安装在手机中,ContentResolver通过acquireProvider请求加载Provider程序。acquireProvider正 是通过解析URI中的authority字段,在安装的package中查找与此authority相符的Provider,如果此Provider没有 被加载ActivityMangerService将加载Provider程序,这个过程可以参考我以前写的Activity是如何加载的文章。 Provider到底是加载到调用Provider的应用程序还是将Provider程序加载到ActivityManagerService中作为 system Provider这个我不太确定是如何区分的,反正这两种方式都是可行的,总之按照sdk help 文档上的方式创建Provider程序,android会自动加载的。
记录的保存与获取
当Camera拍照完成或者是media play文件需要保存的时候,首先要构造保存的数据结构
ContentValues values = new ContentValues(7);
values.put(Images.Media.TITLE, imageName);
values.put(Images.Media.DISPLAY_NAME, imageName);
values.put(Images.Media.DESCRIPTION, description);
values.put(Images.Media.DATE_TAKEN, dateTaken);
values.put(Images.Media.MIME_TYPE, "image/jpeg");
values.put(Images.Media.ORIENTATION, orientation);
Uri uri = cr.insert(sStorageURI, values); //保存到数据库
sStorageURI == content://media/external/sdcard/media/
Authority是 media所以将调用MediaProvider::insert,在insert中生成文件保存的路径并放在key为_data项数据区。再通过 ContentResolver访问MediaProvider调用openFile打开文件并将Image或media数据写入。
Camera,Image gallery应用启动后不会扫描文件系统而是根据数据库的记录来进行列表并显示。这样做无疑效率比较高。
转自百度分享