Android四大组件之ContentProvider

关于ContentProvider

ContentProvider,被称为内容提供者,通过Binder向其他组件以及其他应用提供数据。以某种Uri的形式对外提供数据,允许其他应用访问或修改数据。其他应用程序使用ContentResolver根据Uri去访问操作指定数据。ContentProvider主要以表格的形势组织数据,有行列的层次性。另外还支持图片,视频等。

创建ContentProvider

  • 自定义ContentProvider,该类继承ContentProvider,实现六个必须需要实现的抽象方法
public class MyContentProvider extents ContentProvider{
	/*
	* 创建时被调用
	*/
	@Override
	public boolean onCreate(){
		return false}
	/*
	* 根据Uri查询符合selection条件的全部记录,projection是一个列名列表,选择出指定的数据列,有点sql的select的意思 
	*/
	@Override
	public Cursor query(Uri uri,String[] project,String selection,String[] selectionArgs,String sortOrder){
		//一般使用SQLiteDatabase进行数据的增删查改
		return null;
	}
	/*
	* 返回Uri查询出的selection条件的数据的MIME类型 
	*/
	@Override
	public String getType(Uri uri){
		//当对应多条记录时 以vnd.android.cursor.dir/开头
		//当对应单条记录时 以vnd.android.cursor.item/开头
		return null;
	}
	/*
	* 根据Uri插入对应的value的数据
	*/
	@Override
	public Uri insert(Uri uri,ContentValues values){
		return null;
	}
	/*
	* 根据Uri删除selection匹配的记录
	*/
	@Override
	public int delete(Uri uri,String selection,String[] selectionArgs){
		return 0}
	/*
	* 根据Uri修改selection匹配的记录
	*/
	@Override
	public int update(Uri uri,ContentValues values,String selection,String[] selectionArgs){
		return 0}
}
  • 在AndroidManifest中注册该ContentProvider
<provider
	android:name=".MyContentProvider"
	android:authorities="com.xxxx.xxx.MyContentProvider" //唯一标识,通过它外部应用访问MyContentProvider
	android:exported="true" // 属性用于指示该服务是否能够被其他应用程序组件调用或跟它交互。如果设置为true,则能够被调用或交互,否则不能
	android:multiprocess="true" //为true时:多实例 false:单实例
	/> 

还有一些其他属性
readPermission:使用Content Provider的查询功能所必需的权限,即使用ContentProvider里的query()函数的权限;
writePermission:使用ContentProvider的修改功能所必须的权限,即使用ContentProvider的insert()、update()、delete()函数的权限;
permission:客户端读、写 Content Provider 中的数据所必需的权限名称。readPermission和writePermission属性优先于本设置。 如果同时设置了readPermission属性,则其将控制对 Content Provider 的读取。 如果设置了writePermission属性,则其也将控制对 Content Provider 数据的修改。也就是说如果只设置permission权限,那么拥有这个权限的应用就可以实现对这里的ContentProvider进行读写;如果同时设置了permission和readPermission那么具有readPermission权限的应用才可以读,拥有permission权限的才能写!也就是说只拥有permission权限是不能读的,因为readPermission的优先级要高于permission;如果同时设置了readPermission、writePermission、permission那么permission就无效了。

	android:permission="com.xxx.myPermission"  
    android:readPermission="com.xxx.myPermission.read"  
    android:writePermission="com.xxx.myPermission.write"

Uri组成

如: content://com.xxx.xxx.myContentProvider/hello 分为三部分

  • content:// :类似网络协议的http://
  • com.xxx.xxx.myContentProvider:是指在AndroidManifest中authorities属性,由该部分找到操作的ContentProvider
  • hello:资源部分,访问不同的资源,动态改变

ContentResolver操作数据

首先ContentResolver到底是什么,由上面描述可知,ContentProvide的作用是用来暴露数据,而ContentResolver就是用来操作数据
在这里插入图片描述
由关系图可以看出,当应用A想要对B的数据进行增删查改时,就需要通过ContentResolver来实现。而ContentResolver通过Context提供的 getContentResolver方法获取。然后通过调用ContentResolver的CRUD方法操作数据

  • query(Uri uri,String[] project,String selection,String[] selectionArgs,String sortOrder):当应用A调用该方法时,相当于调用了Uri指向的ContentProvider的query方法
  • insert(Uri uri,ContentValues values)
  • delete(Uri uri,String selection,String[] selectionArgs)
  • public int update(Uri uri,ContentValues values,String selection,String[] selectionArgs)

首先来举例 查询 实例:

参数类型对应SQL部分描述
uriUrifrom table_name查询某个应用程序指定表
projectionString[]select column1,column2指定查询列名
selectionStringwhere column = valuewhere中约束条件
selectionArgsString[]为where中的占位符提供具体的值
orderByStringorder by columns1,column2指定排序方式
//将内容字符串解析成Uri对象
Uri uri = Uri.parse("content://com.xxx.xxx.myContentProvider/hello");
Cursor cursor = getContentResolver().query(uri,project,selection,selectionArgs,sortOrder);
if(cursor!=null){
	while(cursor.moveToNext()){
		String colum1 =cursor.getString(cursor.getColumnIndex("column1"));
		int column2 = cursor.getInt(cursor.getColumnIndex("column2"));
	}
	cursor.close();
}

添加

ContentValues values = new ContentValues();
values.put("column1","text");
values.put("column2",1);
getContentResolver().insert(uri,values);

修改

ContentValues values = new ContentValues();
values.put("column1","");
getContentResolver().update(uri,values,"column1=? and column2 = ?",new String[]{"text","1"});
//使用selection和selectionArgs对想要更新的数据进行约束

删除

getContentResolver().delete(uri,values,"column2=?",new String[]{"1"});
//使用selection和selectionArgs对想要更新的数据进行约束

读取系统ContentProvider

下面展示在实际开发中如何读取系统的联系人。

private void readContacts(){
	Cursor cursor = null;
	try{
		//查询联系人数据
		cursor = getContentResolver().query(
			ContactsContract.commonDataKinds.Phone.CONTENT_URI,
			null,null,null,null);
		while(cursor.moveToNext()){
			//获取联系人姓名
			String Name=cursor.getString(
				cursor.getColumnIndex(ContactContract.CommonDataKinds.Phone.DISPLAY_NAME));
			//存储姓名操作
			//获取联系人手机号码
			String number = cursor.getString(
				cursor.getColumnIndex(ContactContract.CommonDataKinds.Phone.NUMBER));
			//存储手机号码操作
		}
	}catch(Exception e){
		e.printStackTrace();
	}finally{
		if(cursor!=null){
			cursor.close();
		}
	}
}

监听ContentProvider数据变化

  • 操作者
    在操作ContentResolver时,通过调用
getContext().getContentResolver().notifyChange(uri,null);

会通知注册在该Uri的监听者,该ContentProvider上的数据发生了变化

  • 观察者
    要监听指定Uri的ContentProvider的数据变化,需要利用ContentObserver。注册代码如下
/**
*	Uri 指定uri
*	notifyForDescendents :boolean类型,true时,子路径的数据改变也会通知,false:当前路径才通知
*	MyObserver 继承ContentObserver,当所监听数据变化,调用onChange()
*/
getContentResolver().registerContentObserver(uri,true,new MyObserver(new Handler()));

//自定义匿名内部监听类
private final class MyObserver extends ContentObserver{
	public MyObserver(Handler handler){
		super(handler);
	}
	public void onChange(boolean selfChange){
		//当数据改变时执行相应操作
	}
} 

资料

[1] ContentProvider权限设置
[2] 疯狂Android讲义
[3] 第一行代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值