一、Content Provider概述
Content Provider用于保存和获取数据,并使其对所有应用程序可见,这是不同应用程序之间共享数据的唯一方式,因为在Android中没有提供所有应用可以共同访问的公共存储区域
1、 Content Provider内部的数据如何保存是由其设计者决定的,而所有的的Content Provider都实现一组通用的方法,用来提供数据的增删改查操作
2、 客户端如果要使用这些操作方法,可以通过ContentProvider对象实现对 Content Provider的操作,而开发人员可以通过调用getContentResolver()方法来获得ContentProvider对象
即:ContentResolver cr = getContentProvider();
3、 不同进程之间的通信由ContentResolver类和ContentProvider类处理
二、Content Provider提供数据的数据模型
_ID | NAME | AGE |
---|---|---|
001 | Alice | 17 |
002 | Mark | 20 |
003 | Tom | 11 |
可以看出使用的是基于数据库模型的简单表格来提供其中的数据 行:记录 列:字段
*每条记录都包含一个_ID字段,用于在表中唯一标识该记录
ID字段前包含一个下划线_ ,这是必须有的,不能不写
三、URI
1、 每个Content Provider提供公共的URI(使用URI类包装)来唯一标识其数据集
2、 URI常量用于所有与Content Provider的交互,每个Content Provider方法都是用URI作为方法的第一个参数,这个参数(URI)用来标识ContentResolver应该使用Content Provider中的哪一个数据表
3、 URI: content://com.xqx.mycontent/dba/010
(1)content:// :标准的前缀,用于标识该数据由Content Provider管理,固定值,不用修改
(2)com.xqx.mycontent :URI的authority部分,用于标识Content Provider,在清单文件的<provider>元素的authority属性中声明该authority ,对于第三方应用,该部分为完整的类名(全部小写字母)
(3)/dba :路径部分,用于决定哪类数据被请求,如果Content Provider只提供一种数据类型,则可省略该部分、如果提供多种类型,则由多部分组成
(4)/010 :被请求的特定记录的ID ,如果请求的记录不限于单条记录(比如查询全部字段),该部分不用写
四、预定义Content Provider
1、 安卓系统提供了很多预定义的Content Provider(声音,联系人,通话记录等)
Eg:
Browser :读取或修改书签,浏览历史或网络搜索
CallLog :查看或更新通话记录
Contacts: :获取修改或保存联系人信息
MediaStore:访问图片视频音乐等
2、 查询数据
如果想查询Content Provider数据,必须需要三个信息
(1) 标识该Content Provider的URI
(2) 需要查询的数据字段的名称
(3) 字段值数据的类型
*如果查询特定的记录,则还需要提供该记录的ID值
为了限制返回一条数据,可以在URI结尾添加要操作记录的ID,
Content://…./003
实现该功能可以使用静态方法ContentUris.withAppendedId(),返回值为一个增加了ID的URI对象
获得数据用Cursor对象处理,它能向前或向后遍历整个查询结果集。
3、 增加记录
(1) 向ContentProvider中添加数据,需要使用ContentValues对象建立键值对映射,键位Content Provider中的字段,值为要添加的值
(2) 调用ContentResolver.insert(URI,value);
第一个参数为要操作的ContentProvider唯一标识的URI,第二个参数为ContentValues映射 ,该方法返回添加记录的完整的URI
4、 删除记录
(1)需要调用int delete (Uri url, String where, String[] selectionArgs)方法 ,第一个为要操作的URI ,第二个为删除的条件,第三个参数为填充值
int delete (Uri url, “_id=?”, 11) 为删除URI 中id为11的记录
五、 自定义Content Provider
1、 我们从上面了解了开发人员可以使用系统给定的ContentProvide
当然我们也可以自定义ContentProvider来共享自己的数据(当然也可以使用系统预定义的ContentProvider,管理相同的数据并且有写入权限,也可修改对应数据)
自定义ContentProvider步骤
(1)、建立数据存储系统
Android提供了SQLiteOpenHelper 类帮助创建数据库,SQLiteDatabase类帮助管理数据库
(2)、继承ContentProvider
需要重写6个抽象方法
方法 | 说明 |
---|---|
onCreate() | 用于初始化provider |
query() | 返回数据给调用者 |
insert() | 插入新数据到ContentProvider |
updata() | 更新数据 |
delete() | 从ContentProvider中删除数据 |
getType() | 返回CntentProvider数据的MIME类型 |
用于初始化provider query() 返回数据给调用者 insert() 插入新数据到ContentProvider updata() 更新数据 delete() 从ContentProvider中删除数据 getType() 返回CntentProvider数据的MIME类型
eg:
1 package com.example.mycontentprovider;
2
3 import android.content.Context;
4 import android.database.sqlite.SQLiteDatabase;
5 import android.database.sqlite.SQLiteOpenHelper;
6
7 public class DBhelper extends SQLiteOpenHelper{
8 public DBhelper(Context context) {
9 super(context, "users.db", null, 1);
10 }
11
12 @Override
13 public void onCreate(SQLiteDatabase db) {
14 // TODO 初始化数据库
15 db.execSQL("create table t_user(_id integer primary key,uname,upass,money)");
16
17 db.execSQL("create table t_order(_id integer primary key,user_id,price,productname)");
18
19 db.execSQL("insert into t_user(uname,upass,money) values('lisi','123',200)");
20
21 db.execSQL("insert into t_user(uname,upass,money) values('zhangsi','1234',2000)");
22
23
24 }
25
26 @Override
27 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
28 // TODO 数据库升级时执行该方法
29 if(newVersion>oldVersion)
30 {
31 db.execSQL("drop table if exists t_user");
32 db.execSQL("drop table if exists t_order");
33
34 onCreate(db);
35 }
36
37 }
38
39
40
41 }
1 package com.example.mycontentprovider;
2
3 import android.content.ContentProvider;
4 import android.content.ContentUris;
5 import android.content.ContentValues;
6 import android.content.UriMatcher;
7 import android.database.Cursor;
8 import android.database.sqlite.SQLiteDatabase;
9 import android.net.Uri;
10
11 public class UserContentProvider extends ContentProvider{
12 /*
13 * 这里有两个数据表t_user t_order
14 * 给t_user Code标识1
15 * 给t_order Code标识2
16 * 假设当前只对表t_user操作
17 *
18 */
19
20 //声明该ContentProvider的唯一标识
21 public static final String AUTHORITY="com.xqx_mydatabase";
22 //为该组件中可以被外界访问 数据库中的资源定义Code标识
23 public static final int CODE_USER = 1;
24 public static final int CODE_ORDER = 2;
25 //定义访问资源的URI匹配器,使用该类生成被访问的资源的URI
26 private static UriMatcher uriMather;
27 private DBhelper dbhelper;
28 static {
29 uriMather = new UriMatcher(UriMatcher.NO_MATCH);
30 //CODE_USER(1)对应的URI:content://com.xqx_mydatabase/user
31 uriMather.addURI(AUTHORITY, "user", CODE_USER);
32 //CODE_USER(2)对应的URI:content://com.xqx_mydatabase/order
33 uriMather.addURI(AUTHORITY, "order", CODE_ORDER);
34 }
35
36 //删除返回删除成功记录的条数
37 @Override
38 public int delete(Uri uri, String selection, String[] selectionArgs) {
39 // TODO Auto-generated method stub
40 SQLiteDatabase db = dbhelper.getWritableDatabase();
41 if(uriMather.match(uri)==CODE_USER)
42 {
43 //删除t_user表中的数据,返回删除记录的条数
44 int num = db.delete("t_user", selection, selectionArgs);
45 return num;
46 }
47 return 0;
48 }
49
50 @Override
51 public String getType(Uri uri) {
52 // TODO Auto-generated method stub
53 return null;
54 }
55
56 //插入记录
57 @Override
58 public Uri insert(Uri uri, ContentValues values) {
59 // TODO Auto-generated method stub
60 SQLiteDatabase db = dbhelper.getWritableDatabase();
61 if(uriMather.match(uri)==CODE_USER)
62 {
63 //得到插入记录的ID
64 long id = db.insert("t_user", null, values);
65 //返回新插入记录的URI
66 return ContentUris.withAppendedId(uri, id);
67 }
68 return null;
69 }
70
71 //创建DBhelper对象
72 @Override
73 public boolean onCreate() {
74 // TODO Auto-generated method stub
75 dbhelper = new DBhelper(getContext());
76 return false;
77 }
78
79 //查询,返回Cursor对象
80 @Override
81 public Cursor query(Uri uri, String[] projection, String selection,
82 String[] selectionArgs, String sortOrder) {
83 // TODO Auto-generated method stub
84 SQLiteDatabase db = dbhelper.getReadableDatabase();
85 //得到uri对应的Code
86 int code = uriMather.match(uri);
87 Cursor cursor = null;
88 switch (code) {
89 //如果匹配CODE_USER 操作数据表t_user
90 case CODE_USER:
91 //查询数据表t_user
92 cursor = db.query("t_user", projection, selection, selectionArgs, null, null, sortOrder);
93 break;
94 case CODE_ORDER:
95 break;
96 default:
97 break;
98 }
99
100 return cursor;
101 }
102
103 //修改数据表中的数据,返回修改记录的条数
104 @Override
105 public int update(Uri uri, ContentValues values, String selection,
106 String[] selectionArgs) {
107 // TODO Auto-generated method stub
108 SQLiteDatabase db = dbhelper.getWritableDatabase();
109 if(uriMather.match(uri)==CODE_USER)
110 {
111 return db.update("t_user", values, selection, selectionArgs);
112 }
113
114 return 0;
115 }
116
117 }
(3)、在应用程序的AndroidManifest文件中注册Content Provider
1 <!-- 注册 ContentProvider组件
2 android:authorities:声明该组件的唯一标识
3 android:permission:声明该组件的权限
4 android:exported="true":声明该组件可以被外界应用访问
5 -->
6 <provider
7 android:name="com.xqx.UserContentProvider"
8 android:authorities="com.xqx.users"
9 android:permission="com.xqx.READ_WRITE"
10 android:exported="true"
11 />
-----------------------------------------------------------------------------------------------