- Content Provider是什么
在Android系统中,数据的存储方式有很多种,最常用的是SQLite和XML文件的方式。但是这两种方式下,在不同的应用程序间数据是不能直接被相互访问和操作的,鉴于此,同时也为了简化操作,不用经常编写容易出错的SQL语句访问数据库中的数据,google提供了Content Provder—内容提供器,它是一套实现不同应用程序间数据共享的机制,并提供统一的接口供其他程序访问其数据使用。它提供一个类ContentProvider,主要是对Android系统中进行共享的数据进行包装,相当于一个共享数据库表,并通过ContentResolver提供了一组增删改查的接口供其他程序使用。可以理解为Content Provider使android系统数据库中的数据共享出来,能够被其他程序访问,但是访问方式不是任意的,只能通过它规定好的方式,这种方式就是通过ContentResolver来实现。
Android内置的很多数据都是使用ContentProvider的形式供开发者调用,包括视频、音频、图片、通讯录等。
- Content Provider使用方法
1.URI
事实上,Content Provider的用户都不可能直接访问到ContentProvider的实例,只能通过ContentResolver在中间代理。每个ContentProvider定义一个唯一的公开的URI,用于指定到它的数据表。一个ContentProvider实例可以包含多个数据表,这样,一个ContentProvider实例就需要有多个URI与它包含的每个数据表对应。
URI以content: //开头,表示这个URI指定一个ContentProvider。
示例URI:
content://media/internal/images
(返回设备上存储的所有图片)
content://contacts/people/
(返回设备上的所有联系人信息)
content://contacts/people/45
(返回单个结果:联系人信息中ID为45的联系人记录)
总结:URI代表数据的路径和一个标识数据的ID(可选)。
Android提供了一系列的帮助类(在android.provider包中),里面包含了很多以类变量形式给出的查询字符串,例如:
MediaStore.Image.Thumbnails
MediaStore.Image.Media
在这些类的后面加上EXTERNAL_CONTENT_URI就得到了一个Uri对象。
2.ContentResolver类
当其他应用程序需要对ContentProvider中的数据进行增删改查时,需要使用ContentResolver类来完成,因此访问ContentProvider的第一步是要获取ContentResolver对象。获取方法是:
ContentResolver cr = context.getContentResolver();
(其中context可以是Activity或者Service)
3.查询
Cursor cursor = getContentResolver().query(
Uri,
Projection,
Selection,
selectionArgs,
sortOrder);
参数详解:
Uri:这个是必选参数,其他均为可选,指定查询某个应用程序下的某一张表;
Projection:指定查询的列名,可以为null,表示取数据集的全部列,或者声明一个String数组,数组中存放列名称。一般列名在Android提供的contentprovider中都有常量对应;
Selection:指定约束条件,也就是返回结果的过滤器,相当于SQL中的Where子句;
selectionArgs:过滤器的参数,是String数组,是针对约束条件中的?占位符的值,见示例:
Cursor cursor= getContentResolver().query(uri,null
MediaStore.Image.Media.MIME_TYPE + “=? or”
+MediaStore.Image.Media.MIME_TYPE + ”=?”,
new String[]{ “image/jpeg”,”image/png”},
MediaStore.Images.Media.Date_MODIFIED);
SortOrder:排序参数,不排序可以设置为null。
查询完成后返回的是一个Cursor对象,可以通过移动游标的位置来遍历Cursor的所有行,然后再取出每一行中的相应列的数据,可以通过getString(columnIndex)、getInt(columnIndex)、getFloat(columnIndex)等方法获取数据值。
4.增加insert
5.删除delete
6.更新update
- ContentProvider工作原理
每个ContentProvider类似一个单个数据库表,不同的content provider会有不同的列和名称,但是会有一个相同的列_ID,用来标识记录,访问ContentProvider其实就是访问一张数据库表。
在Android系统中,已经为我们提供了许多ContentProvider,如Contacts、Browser、CallLog、Settings、MediaStore等,本原型系统中用到的是MediaStore。
下面以系统需求为例,介绍ContentProvider的使用方法和原理。
在Android中,多媒体文件(视频和图像)都是有缩略图的。系统需要实现一个自定义gallery,因此首先需要扫描系统相册里面的图片,然后获取其缩略图,使用GridView去展示缩略图,当点击单个Item之后,又需要获取其原始图像进行显示。所以实现这个功能要进过两个步骤:
- 获取缩略图
- 找到缩略图和原始图像之间的关联,即如何通过缩略图找到原始图像。
1.获取缩略图
获取缩略图可以直接查询:
MediaStore.Images.Thumbnails这个ContentProvider,也就是一张数据库表。
具体方法
Uri mThumbnailUri = MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI;
String[ ] projection = {Thumbnails._ID, Thumbnails.IMAGE_ID, Thumbnails.DATA};
Cursor cursor = getContentResolve().query
(mThumbnailUri, projection ,null, null, null);
2.获取原始图像类似
3.关联
关联原理:查询Android系统中Media的.db数据库文件,可以看到该数据库中有很多数据表,其中有images表和thumbnails表。打开thumbnails表可以看到每张缩略图都有_id和image_id两个字段;打开images表可以看到每张图像也都有_id和_data字段,而且_data字段就是图像所在的绝对路径,_id字段和thumbnail表里面的image_id字段一一对应,这样通过缩略图的image_id字段就能查询到缩略图对应的原始图像的_id,近而得到原始图像的绝对路径。
(代码见原型系统)