如何通过contentprovider构建媒体文件数据库_第1页
如何通过contentprovider构建媒体文件数据库_第2页
如何通过contentprovider构建媒体文件数据库_第3页
如何通过contentprovider构建媒体文件数据库_第4页
如何通过contentprovider构建媒体文件数据库_第5页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Android如何通过content provider构建媒体文件数据库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 mArtistCache = new HashMap();HashMap mAlbumCache = new HashMap();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 /第一次打开数据库时创建Tablepublic 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加载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应用启动后不会扫描文件系统而是根据数据库的记录来进行列表并显示。这样做无疑效率比较高。文件的删除数据库中保存有文件的路径名,当调用delete从数据库中删除一个记录后,记录中_data保存的文件名(绝对路径)所指的文件也被删除了。而在应用程序中是找不到删除文件的代码,这个困扰了我两天,在程序中加log,分析源代码,最终屏蔽MediaProvider中的一段代码找到了一点线索:public int delete(Uri uri, String userWhere, String whereArgs) int count;int match = URI_MATCHER.match(uri);.if (match != VOLUMES_ID) DatabaseHelper database = getDatabaseForUri(uri);if (database = null) throw new UnsupportedOperationException(Unknown URI: + uri);SQLiteDatabase db = database.getWritableDatabase();synchronized (sGetTableAndWhereParam) getTableAndWhere(uri, match, userWhere, sGetTableAndWhereParam);switch (match) case AUDIO_MEDIA:case AUDIO_MEDIA_ID:count = db.delete(audio_meta,sGetTableAndWhereParam.where, whereArgs);break;default:/ count = db.delete(sGetTableAndWhereParam.table,/ sGetTableAndWhereParam.where, whereArgs);break;getContext().getContentResolver().notifyChange(uri, null);.将上面红色代码注掉以后发现文件没有被删除,而红色代码只是对数据库进行操作,因而文件应该是在清除数据库的记录时候被删除的。仔细查看创建table的代码发现几个语句很奇怪,由于没有网络去搜索一下关于android SQL的knowledge 只能猜测这个语句的意思了当然也怪偶没去学学SQL。 db.execSQL(CREATE TRIGGER IF NOT EXISTS images_cleanup DELETE ON images +BEGIN +DELETE FROM thumbnails WHERE image_id = old._id; +SELECT _DELETE_FILE(old._data); +END);创建table为 images的触发器,DELETE FROM thumbnails WHERE image_id = old._id正是删除thumbnails的意思,对于Camera创建的Images会生成一个小图片保存为thumbnail,这个记录也是自动清除的。 SELECT _DELETE_FILE(old._data); 应该是删除文件的意思。在Sqlite3_android.cpp文件中还真找到delete_file这个函数,加上log,进入gallery选择一个文件删除,打出了删除文件名的全路径。static void delete_file(sqlite3_context * context, int argc, sqlite3_value * argv).if (strncmp(/sdcard/, path, 8) != 0) /只能删除sdcard/路径下的东西要删除其他路sqlite3_result_null(context); /还需稍微改造一下return;如何将文件保存在手机上MediaProvider中存在两个数据库一个是external对应文件系统为SD Card, 一个是内部数据库internal用于手机flash上的文件系统。遗憾的是虽然MediaProvider提供了操作内外两个数据库的功能,但在发布的应用中并没有使用这个内部文件系统。Android 默认状态下Image,audio等文件是保存在SD card上。External, internal 数据库都保存在手机文件系统上Path: /data/data/viders.media/database/如果要使用内部文件系统需要修改以下几个地方1:MediaProvider generateFileName函数private String generateFileName(boolean internal, String preferredExtension, String directoryName)/ create a random fileString name = String.valueOf(System.currentTimeMillis();if (internal) throw new UnsupportedOperationException(Writing to internal storage is not supported.);/ return Environment.getDataDirectory()/ + / + directoryName + / + name + preferredExtension; else return Environment.getExternalStorageDirectory()+ / + directoryName + / + name + preferredExtension;恢复红色部分代码,将路径设置为手机内部文件系统文件夹。2:保存文件使用的URI为content:/media/internal/images/media/1红色internal表名使用内部文件系统数据库3:修改Sqlite3_android.cpp中delete_file函数static void delete_file(sqli

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论