—— 星光不问赶路人,时光不负有心人。
ContentProvider 帮助应用与其他应用共享数据。如果我的应用实现并提供了 ContentProvider,其他应用可以通过 ContentResolver 访问我的应用中实现的 ContentProvider。ContentProvider 提供查询、插入、更新或删除等 API 以及数据库。
其他应用可以使用 ContentProvider 提供的 API 读取、保存和删除数据。当然,您需要使用 SQLite 等数据库在内部管理数据。您可以将 ContentProvider 视为与其他应用程序共享数据的接口。
ContentProvider定义和访问限制
AndroidManifest.xml ContentProvider 可以定义如下:android:authorities该属性与 ContentProvider ID 相同。在其他应用中搜索我的应用的Provider时需要知道权限。
1
2
3
4
5
6
7
8
|
android:name = ".SampleContentProvider" android:exported = "true" android:readPermission = "com.harvic.contentProviderBlog.READ" android:writePermission = "com.harvic.cotentProviderBlog.WRITE" /> |
android:permission:应用程序读、写 ContentProvider 中的数据所必需的权限名称。 本属性为一次性设置读和写权限提供了快捷途径。 不过,readPermission和writePermission属性优先于本设置。 如果同时设置了readPermission属性,则其将控制对 Content Provider 的读取。 如果设置了writePermission属性,则其也将控制对 Content Provider 数据的修改。也就是说如果只设置permission权限,那么拥有这个权限的应用就可以实现对这里的ContentProvider进行读写;如果同时设置了permission和readPermission那么具有readPermission权限的应用才可以读,拥有permission权限的才能写!也就是说只拥有permission权限是不能读的,因为readPermission的优先级要高于permission;如果同时设置了readPermission、writePermission、permission那么permission就无效了。
ContentProvider方法
ContentProvider 提供查询、插入、更新或删除等 API 以及数据库。如果您知道 Provider 的授权,您的应用可以使用 ContentProvider 访问 Provider。
查询
首先,您可以创建一个具有权限的 Uri,并将此 Uri 作为参数传递给 ContentResolver 以进行查询。查询API 的使用类似于 SQLite 等数据库。您可以设置查询等操作来找到您需要的数据。然后,您可以通过返回的 Cursor 对象读取数据。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
String table_name = "cheeses" ; String authority = "com.example.contentprovidersample.provider" ; Cursor cursor = getContentResolver().query( uri, // uri null , // projection null , // selection null , // selectionArgs "id" // sortOrder ); if (cursor!= null ) { cursor.moveToFirst(); do { int idIndex= cursor.getColumnIndex( "id" ); int id= cursor.getInt(idIndex); int nameIndex= cursor.getColumnIndex( "name" ); String name= cursor.getString(nameIndex); } while (cursor.moveToNext()); } |
一个Uri由以下几部分组成:
1
2
3
4
|
Authority:授权信息,用以区别不同的ContentProvider; Path:表名,用以区分ContentProvider中不同的数据表; Id:Id号,用以区别表中的不同数据; |
如以上例子中的URI_CHEESE就表示cheeses这张表,如果改成
1
2
3
|
int ID = 5 ; |
就表示cheeses这张表中的id为5的这条数据。所以上面例子就表示使用query方法查询cheeses这张表并返回游标Cursor,query方法有五个参数:
1
2
3
4
5
6
|
第一个参数uri:可以理解为作为标识是操作哪个ContentProvider,uri也可以理解为是ContentProvider的具体 "路径" ,如上面例子中的 "路径" 就表示是cheeses表; 第二个参数projection:查询cheeses表哪几列数据, null 表示查询所有列; 第四个参数selectionArgs:查询条件的值,与第三个参数selection搭配使用; 第五个参数sortOrder:查询按某列排序,如上面例子中是按ID升序排列,也可以写成 "id ASC" ,降序就是 "id DESC" ; |
插入
1
2
3
4
5
6
|
ContentValues contentValues = new ContentValues(); contentValues.put( "name" , "张三" ); contentValues.put( "email" , "123@qq.com" ); getContentResolver().insert(contentUri, contentValues); |
更新
1
2
3
4
5
6
7
8
|
ContentValues contentValues = new ContentValues(); contentValues.put( "name" , "张三" ); contentValues.put( "email" , "123@qq.com" ); String whereClause = "id = ?" ; String placeHolderValueArr[] = { "1" }; getContentResolver().update(contentUri, contentValues, whereClause , placeHolderValueArr); |
删除
1
2
3
4
5
|
String whereClause = "id = ?" ; String placeHolderValueArr[] = { "1" } getContentResolver().delete(contentUri, whereClause , placeHolderValueArr); |
异步操作
在Activity和Fragment中可以使用LoaderManager和CursorLoader异步访问ContentProvider。当LoaderManager获取到Provider的所有数据后,会通过LoaderCallbacks进行回调。当 Provider 数据由于添加、删除、更新等发生变化时,它也会回调。