数据库文件一般是私有的,别的应用程序是没办法访问私有的数据库。而有些应用的需求是需要把自己私有的数据暴露给别的应用程序访问,因此就需要用到ContentProvider了
例如系统应用短信、联系人等都需要暴露自己的数据给其他第三方应用访问。
原理是该应用通过ContentProvider来暴露数据供其它应用访问,然后其他应用使用ContentResolver通过Uri来对该应用的数据库进行操作。
ContentProvider中的主要方法,其子类必须实现
boolean onCreate() --> 初始化数据
String getType(Uri uri) --> 根据Uri返回相应的MIME类型(一般默认返回null即可)
Uri insert(Uri uri, ContentValues values) --> 根据Uri插入一条数据
int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) --> 根据Uri更新一条数据
int delete(Uri uri, String selection, String[] selectionArgs) --> 根据Uri删除一条数据
Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) --> 根据Uri查询数据并返回Cursor
now,就以一个demo来介绍如何通过ContentResolver来访问ContentProvider暴露出来的数据吧。
要暴露数据的应用(ContentProvider)
首先,假定应用的数据库已经创建好了,也写入了一些记录。
第一步:创建一个ClientProvider类并继承ContentProvider,复写父类的方法,并完成初始化
PersonDBOpenHelper helper;
@Override
public boolean onCreate() {
helper = new PersonDBOpenHelper(getContext());
return true;
}
@Override
public String getType(Uri uri) {
return null;
}
第二步:添加一个Uri匹配器,并设置匹配规则
/**
* 创建一个uri的匹配器(UriMatcher)
* 如果路径匹配不成功就返回 -1
*/
private static UriMatcher um = new UriMatcher(-1);
static{
/**
* 添加一个uri的匹配规则
* authorities:和清单文件里面的要一致
* path:用于区分uri,可以写多个,以“/”分隔;例如有多张表时可以【<表名>/query】
* code:用于确认此uri
*/
um.addURI("cn.rixin.sqlite.rixindb", "query", 1);//content://cn.rixin.sqlite.rixindb/query 查询
um.addURI("cn.rixin.sqlite.rixindb", "insert", 2);//content://cn.rixin.sqlite.rixindb/insert 添加
um.addURI("cn.rixin.sqlite.rixindb", "delete", 3);//content://cn.rixin.sqlite.rixindb/delete 删除
um.addURI("cn.rixin.sqlite.rixindb", "update", 4);//content://cn.rixin.sqlite.rixindb/update 更新
}
第三步:对数据库进行增删改查操作
添加记录
@Override
public Uri insert(Uri uri, ContentValues values) {
//uri用户操作的路径。 检查uri是否合法。
int result = um.match(uri);
if(result == 2){ // 对应Uri中的code
SQLiteDatabase db = helper.getWritableDatabase();
long id = db.insert("info", null, values);
db.close(); // 用完记得要关闭数据库
return ContentUris.withAppendedId(uri, id); // 添加一个id进Uri中并返回
}else{
throw new RuntimeException("uri路径错误,不告诉你数据!!!");
}
}
删除记录
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
//uri用户操作的路径。 检查uri是否合法。
int result = um.match(uri);
if(result == 3){ // 对应Uri中的code
SQLiteDatabase db = helper.getWritableDatabase();
int i = db.delete("info", selection, selectionArgs);
db.close(); // 用完记得要关闭数据库
return i; //返回受影响的行数
}else{
throw new RuntimeException("uri路径错误,不告诉你数据!!!");
}
}
更改记录
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
//uri用户操作的路径。 检查uri是否合法。
int result = um.match(uri);
if(result == 4){ // 对应Uri中的code
SQLiteDatabase db = helper.getWritableDatabase();
int i = db.update("info", values, selection, selectionArgs);
db.close(); // 用完记得要关闭数据库
return i; //返回受影响的行数
}else{
throw new RuntimeException("uri路径错误,不告诉你数据!!!");
}
}
查询记录
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
//uri用户操作的路径。 检查uri是否合法。
int result = um.match(uri);
if(result == 1){ // 对应Uri中的code
//查询数据,返回数据
SQLiteDatabase db = helper.getReadableDatabase();
Cursor cursor = db.query("info", projection, selection, selectionArgs, null, null, sortOrder);
db.close(); // 用完记得要关闭数据库
return cursor; // 返回查询得到的结果集
}else{
throw new RuntimeException("uri路径错误,不告诉你数据!!!");
}
}
最后一步:也是最最容易忘记的一步,在清单文件中的application里面配置内容提供者和权限
配置完整类路径,主机名(一般写为【<packagename>+数据库名】),还有一定要设置exported属性为true;然后设置读写权限
<permission android:name="cn.rixin.sqlite.READ" ></permission>
<permission android:name="cn.rixin.sqlite.WRITE"></permission>
<application>
<provider
android:name="cn.rixin.sqlite.ClientProvider"
android:authorities="cn.rixin.sqlite.rixindb"
android:readPermission="cn.rixin.sqlite.READ"
android:writePermission="cn.rixin.sqlite.WRITE"
android:exported="true">
</provider>
</application>
其他应用(ContentResolver)
第一步:获取内容提供者的解析器
ContentResolver resolver = getContentResolver();
第二步:进行数据的增删改查操作
添加记录
/**
* 测试添加
*/
public void testInsert(View view){
//利用内容提供者获取数据库db应用的数据
resolver = getContentResolver();
//利用解析器通过ClientProvider获取数据
Uri uri = Uri.parse("content://cn.rixin.sqlite.rixindb/insert");
ContentValues values = new ContentValues();
values.put("username", "Linda");
values.put("password", "123456");
Uri uriResult = resolver.insert(uri, values);
if(uriResult != null){
Toast.makeText(this, "添加SQLite应用中的数据成功", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(this, "添加SQLite应用中的数据失败", Toast.LENGTH_SHORT).show();
}
}
删除记录
/**
* 测试删除
*/
public void testDelete(View view){
//利用内容提供者获取数据库db应用的数据
resolver = getContentResolver();
//利用解析器通过ClientProvider获取数据
Uri uri = Uri.parse("content://cn.rixin.sqlite.rixindb/delete");
int i = resolver.delete(uri, "username=?", new String[]{"Linda"});
if(i > 0){
Toast.makeText(this, "删除SQLite应用中的数据成功", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(this, "删除SQLite应用中的数据失败", Toast.LENGTH_SHORT).show();
}
}
更改记录
/**
* 测试更新
*/
public void testUpdate(View view){
//利用内容提供者获取数据库db应用的数据
resolver = getContentResolver();
//利用解析器通过ClientProvider获取数据
Uri uri = Uri.parse("content://cn.rixin.sqlite.rixindb/update");
ContentValues values = new ContentValues();
values.put("password", "1008611");
int i = resolver.update(uri, values, "username=?", new String[]{"Linda"});
if(i > 0){
Toast.makeText(this, "更新SQLite应用中的数据成功", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(this, "更新SQLite应用中的数据失败", Toast.LENGTH_SHORT).show();
}
}
查询记录
/**
* 测试查询
*/
public void testQuery(View view){
//利用内容提供者获取数据库db应用的数据
resolver = getContentResolver();
//利用解析器通过ClientProvider获取数据
Uri uri = Uri.parse("content://cn.rixin.sqlite.rixindb/query");
Cursor cursor = resolver.query(uri, null, null, null, null);
while(cursor.moveToNext()){
int id = cursor.getInt(cursor.getColumnIndex("_id"));
String username = cursor.getString(cursor.getColumnIndex("username"));
String password = cursor.getString(cursor.getColumnIndex("password"));
Toast.makeText(this, id+"---"+username+"---"+password, 0).show();
}
cursor.close();
}
第三步:也是最最容易忘记的一步,配置权限
<uses-permission android:name="cn.rixin.sqlite.READ"/>
<uses-permission android:name="cn.rixin.sqlite.WRITE"/>
至于获取短信,联系人等系统应用中的数据的方法,这里就不说了,大家可以google搜索学习哈...
希望以上对您有所帮助。欢迎指(吐)正(嘈)