第七章 内容提供者
内容提供者主要用在不同应用程序之间实现数据共享。
内容提供者用法一般有两种:
1、使用现有的内容提供器,来读取和操作相应程序中的数据。
2、创建字节的内容提供器,为我们程序的数据提供外部访问接口。
一、访问其他应用程序中的数据
1.ContentResolver 类
可以通过Context的getContentResolver()方法获取到该类的实例对象。
CRUD 方法:
添加数据:inset();
更新数据:update();
删除数据:delete();
查询数据:query();
以上方法第一个参数是一个内容URI,内容URI的组成:协议声明、权限、路径
协议:"content://"
权限:一般用包名。例如:"com.example.app"
路径:数据库中的表名。例如:"table1"
示例数据:content://com.example.app/table1
- 得到URI之后我们还需要将他解析成Uri对象。
Uri uri = Uri.parse("cotent://com.example.app/table1");
- 查询数据
Cursor cursor = getContentResolver().query(uri,projection,selection,selectionArgs,sortOrder);
uri:制定查询某个应用程序下的某张表。
projection:指定查询的列名。
selection:指定where的约束条件。
selectionArgs:指定where的占位符。
sortOrder:指定查询结果的排序方式
查询完成后返回的是一个Cursor对象,遍历Cursor对象获取数据。
Cursor cursor = null;
if (cursor != null){
while (cursor.moveToNext()){
String column1 = cursor.getString(cursor.getColumnIndex("列名"));
}
cursor.close();
}
添加数据
// 利用ContentValues添加数据
ContentValues values = new ContentValues();
values.put("列名1","数据1");
values.put("列名2","数据2");
getContentResolver().insert(uri,values);-
更新数据
ContentValues values = new ContentValues(); values.put("列名1",""); getContentResolver().update(uri,values,"列名1 = ? and 列名2 = ?",new String[]{"text","1"});
删除数据
getContentResolver().delete(uri,"列名 = ?",new String[]{"1"});
二、读取联系人Demo
关键代码
private void readContacts(){
Log.d("WSJ","开始读取联系人");
Cursor cursor = null;
try {
// 查询联系人
cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,null,null,null);
while (cursor.moveToNext()){
// 获取姓名
String displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
// 获取手机号码
String displayNum = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
// 保存联系人
mList.add(displayName + "\n" + displayNum);
}
}catch (Exception e) {
Log.d("WSJ","读取联系人失败");
}finally {
if (cursor != null){
cursor.close();
}
}
权限声明
三、创建自己的内容提供者
- 通过新建一个ContentProvider的子类,实现以下 6 个方法:
class MyProvider extends ContentProvider{
/*
* 1, 初始化方法,在这里完成数据库的创建和升级,true表示初始化成功。
* 只有当存在ContentResolver尝试访问我们程序中的数据时,内容提供者才会初始化
* */
@Override
public boolean onCreate() {
return false;
}
/*
* 2, 查询数据
* uri :确定那张表。
* projection : 指定查询的列。
* selection :查询的行约束。
* selectionArgs:selection中的占位符数据。
* sortBy :对结果进行排序。
* 查询结果保存在Cursor对象中。
* */
@Nullable
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] slectionArgs, String sortBy) {
return null;
}
/*
* 3, 添加数据
* */
@Nullable
@Override
public Uri insert(Uri uri, ContentValues contentValues) {
return null;
}
/*
* 4,更新数据
* */
@Override
public int update(Uri uri, ContentValues contentValues, String s, String[] strings) {
return 0;
}
/*
* 5, 删除数据
* */
@Override
public int delete(Uri uri, String s, String[] strings) {
return 0;
}
/*
* 6, 获取MIME
* */
@Nullable
@Override
public String getType(Uri uri) {
return null;
}
}
- Uri 数据解析
(1)内容Uri的格式主要有两种:
1、以路径结尾获取表中所有数据:content://com.example.app.provider/table1
2、以id访问拥有指定id的数据:content://com.example.app.provider/table1/1
(2)通配符使用方式
1、* : 表示匹配任意长度、任意字符。
匹配任意表内容的URI : content://com.example.app.provider/*
2、# : 表示匹配任意数组、任意长度。
匹配table1中的任意一行数据:content://com.example.app.provider/table1/#
(3)UriMatcher 类实现匹配URI的功能。
1、UriMatcher类的addURI()方法。接收三个参数:权限、路径、自定义代码。
2、UriMatcher类的match()方法。接收一个Uri对象,返回一个自定义代码。
示例代码
private static final int TABLE1_DIR = 0;
private static final int TABLE1_ITEM = 1;
private static final int TABLE2_ITEM = 2;
private static final int TABLE2_DIR = 3;
private static UriMatcher uriMatcher;
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI("com.example.app.provider","table1",TABLE1_DIR);
uriMatcher.addURI("com.example.app.provider","table1/#",TABLE1_ITEM);
uriMatcher.addURI("com.example.app.provider","table2",TABLE2_DIR);
uriMatcher.addURI("com.example.app.provider","table2/#",TABLE2_ITEM);
}
public Cursor query1(Uri uri, String[] projection, String selection, String[] slectionArgs, String sortBy) {
switch (uriMatcher.match(uri)){
case TABLE1_DIR:
// 查询table1中的所有数据。
break;
case TABLE1_ITEM:
// 查询table1中的单条数据。
break;
case TABLE2_DIR:
// 查询table2中的所有数据。
break;
case TABLE2_ITEM:
// 查询table2中的单条数据。
break;
}
return null;
}
MIME字符串
MIME字符串由 3 部分组成,Android对这三部分做了如下规定。
1、必须以 vnd 开头。
2、内容以路径结尾,则后接 android.cursor.dir/
内容以id结尾,则后接 android.cursor.item/
3、最后接上 : vnd..
对于URI : content://com.example.app.provider/table1
对应MIME :vnd.android.cursor.dir/vnd.com.example.app.provider.table1
示例代码
public String getType(Uri uri) {
switch (uriMatcher.match(uri)){
case TABLE1_DIR:
return "vnd.android.cursor.dir/vnd.com.example.app.provider.table1";
case TABLE1_ITEM:
return "vnd.android.cursor.dir/vnd.com.example.app.provider.table1";
default:
return null;
}
}