Content providers存储和检索数据并使其可以让所有apps访问,公开自己数据的两种方法:创建自己的provider或者把数据加到现有的provider里面。
基础
所有的content provider都现一个为provider查询和返回结果的公共接口,这是一个客户端直接使用的接口,通常都是通过contentresolver对象访问。
ContentResolver cr = getContentResolver();
URIs
每个provider都会暴露一个公共的URI用来唯一定位它的数据集,提供多个数据集的content provider会为每个数据集提供一个URI,所有URI都是由“content://”开头。最好为URI提供一个constant(android.provider.Contacts.Phones.CONTENT_URI ),这会简化客户端的代码,而且让将来升级更干净。
查询ContentProvider
You need three pieces of information to querya content provider:
- The URI that identifies the provider
- The names of the data fields you want to receive
- The data types for those fields
如何查询
使用ContentResolver.query()or Activity.managedQuery()方法,后者可以让系统帮你管理cursor的状态。系统还提供了更好用的方法以便查询URI的某条记录,它们是ContentUris.withAppendedId() orUri.withAppendedPath()。
// Use the ContentUris method to produce the base URI forthe contact with _ID == 23.
Uri myPerson = ContentUris.withAppendedId(People.CONTENT_URI, 23);
// Alternatively, use the Urimethod to produce the base URI.
// It takes a string ratherthan an integer.
Uri myPerson = Uri.withAppendedPath(People.CONTENT_URI, "23");
// Then query for thisspecific record:
Cursor cur = managedQuery(myPerson, null, null, null, null);如果查询返回的是二进制数据,例如:图像或声音,数据会直接写进表里;通常,小量的数据(20k-50k)会直接写进表里,可以通过Cursor.getBlob()来访问,它将会返回一个二进制数组。
假如表的入口是content:URI,你必须调用ContentResolver.openInputStream()返回的inputStream对象来读取数据。
修改数据
修改方式:增加新纪录、在现有纪录里增加值、批量更新现有纪录、删除纪录,所有的数据修改都是通过ContentResolver的方法实现的,调用其方法的前提是你必须有操作的权限。
增加新纪录
ContentValues values = new ContentValues(); // Add Abraham Lincoln to contacts and make him a favorite. values.put(People.NAME, "Abraham Lincoln"); // 1 = the new contact is added to favorites // 0 = the new contact is not added to favorites values.put(People.STARRED, 1); Uri uri = getContentResolver().insert(People.CONTENT_URI, values);
增加新值
Uri phoneUri = null;
Uri emailUri = null;
// Add a phone number forAbraham Lincoln. Begin with the URI for
// the new record justreturned by insert(); it ends with the _ID
// of the new record, so wedon't have to add the ID ourselves.
// Then append thedesignation for the phone table to this URI,
// and use the resulting URIto insert the phone number.
phoneUri = Uri.withAppendedPath(uri, People.Phones.CONTENT_DIRECTORY);
values.clear();
values.put(People.Phones.TYPE, People.Phones.TYPE_MOBILE);
values.put(People.Phones.NUMBER, "1233214567");
getContentResolver().insert(phoneUri, values);
// Now add an email addressin the same way.
emailUri = Uri.withAppendedPath(uri, People.ContactMethods.CONTENT_DIRECTORY);
values.clear();
// ContactMethods.KIND isused to distinguish different kinds of
// contact methods, such asemail, IM, etc.
values.put(People.ContactMethods.KIND, Contacts.KIND_EMAIL);
values.put(People.ContactMethods.DATA, "test@example.com");
values.put(People.ContactMethods.TYPE, People.ContactMethods.TYPE_HOME);
getContentResolver().insert(emailUri, values); 像小型的icon图片或者音频短片可以直接put到values里面,但如果是照片或者是一首完整的歌,则必须把文件的content:URI放到表里并用文件的URI调用ContentResolver.openOutputStream()方法。为此,系统专门提供了MediaStore provider以处理这类数据。如下:
// Save the name and description of an image in aContentValues map.
ContentValues values = new ContentValues(3);
values.put(Media.DISPLAY_NAME, "road_trip_1");
values.put(Media.DESCRIPTION, "Day 1, trip to Los Angeles");
values.put(Media.MIME_TYPE, "image/jpeg");
// Add a new record withoutthe bitmap, but with the values just set.
// insert() returns the URIof the new record.
Uri uri = getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, values);
// Now get a handle to thefile for that record, and save the data into it.
// Here, sourceBitmap is aBitmap object representing the file to save to the database.
try {
OutputStream outStream = getContentResolver().openOutputStream(uri);
sourceBitmap.compress(Bitmap.CompressFormat.JPEG, 50, outStream);
outStream.close();
} catch (Exception e) {
Log.e(TAG, "exception while writing image", e);
}批量更新纪录
参见ContentResolver.update()方法。
删除纪录
参见ContentResolver.delete()方法
创建一个Content Provider
创建必须要做的事:
² 建立一个存储数据的系统
² 继承ContentProvider类来提供数据的访问
² 在app的manifest里面声明它
继承ContentResolver类
1. 实现主要抽象方法:
query()
insert()
update()
delete()
getType()
onCreate()
2. 定义一个public static finalUri CONTENT_URI,唯一标识
public static final Uri CONTENT_URI =
Uri.parse("content://com.example.codelab.transportationprovider");
如果有子表,则要保证它们有相同的授权,而且要为每个子表定义一个唯一的URI,如:
content://com.example.codelab.transportationprovider/train
content://com.example.codelab.transportationprovider/air/domestic
3. 定义返回给客户端的列名,public static类型的,而且要保证有个自增的ID。
4. 仔细文档化每列的数据类型
5. 如果要存储大文件,暴露给客户端的字段需要包含conent:URI,以便存储和访问文件
6. 声明它
<provider android:name="com.example.autos.AutoInfoProvider"
android:authorities="com.example.autos.autoinfoprovider"
. . . />
</provider>
本文深入探讨了Android应用中使用内容提供者(ContentProvider)进行数据存储与检索的方法,包括创建自定义提供者、操作URI、查询与修改数据的流程,以及如何在不同场景下高效利用ContentResolver进行数据交互。

6028

被折叠的 条评论
为什么被折叠?



