什么是ContentProvider?
1:内容提供者,通过ContentProvider可以在应用之间彼此访问数据,是and推荐的标准的应用之间访问数据的统一接口;
2:大致有两种应用;通过ContentResolver访问系统或者其他应用的数据,通过自定义contentprovider向外提供数据;
3:访问原理:使用ContentResolver的CURD方法;通过目标ContetnProvider提供的uri来操作数据;
4:Uri:contentProvider向外提供的一个访问数据的资源标识符;可以通过该URL对其ContentProvider的数据进行操作;
URI:
1:URI:
URI由四部分组成:content://com.example.ContentProvider_name/table_name/id;
content://:标志部分;说明这个uri指向一个contentProvider;
com.example.ContentProvider_name:URI标识;指向一个确定的ContentProvider;由包名和类名组成,且必须全部小写;
table_name:路径:有可能是表的名字;也可根据录的ID;具体业务自定义;如果是XML文件的话就是一级节点/二级节点/以此类推;
id:标识需要操作的字段;
2:URI操作:
2.1 URI的转换:
Uri uri = Uri.prase(“String”);
//String=content://com.example.ContentProvider_name/table_name/id
2.2:注册URI:
常用的uri模式有两种:
//获取全部数据
content://com.example.ContentProvider_name/table_name/
//获取某条数据
content://com.example.ContentProvider_name/table_name/#
在自定义contentProvider中;我们需要根据传来的uri来判断需要操作哪一个数据表以及执行那种操作,就需要对uri进行匹配;
此时就要用到UriMatcher了:
具体操作如下:(对query,insert,delete,update)都要有这个匹配过程
// 创建UriMatcher对象:
1:UriMatcher urimatcher = new UriMatcher(UriMatcher.NO_MATCH);
// 添加uri字符串,和返回码;到时候传来的uri就会在添加的这几个uri中匹配
2:
urimatcher.addUri("权限","路径",int 返回码);
urimatcher.addUri("com.example.ContentProvider_name","table_name1", 0);
urimatcher.addUri("com.example.ContentProvider_name","table_name1/id", 1);
urimatcher.addUri("com.example.ContentProvider_name","table_name2", 2);
urimatcher.addUri("com.example.ContentProvider_name","table_name2/id", 3);
// 进行返回码匹配以确定正在请求哪个数据
3:switch(urimatcher.match(Uri uri)){
case 0:
//操作table_name1,取出全部数据;
break;
case 1:
//操作table_name1,取出指定数据;
break;
case 2:
//操作table_name2,取出全部数据;
break;
case 3:
//操作table_name2,取出指定数据;
break;
default:
Log.i("urimatch","全不匹配");
break;
}
2.3:操作URI的参数部分;
ContentUris用于操作Uri路径后面的ID部分:
//追加ID:
Uri uri = Uri.prase(content://com.example.ContentProvider_name/table_name/?)
Uri uris = ContentUris.withAppendId(uri,10);
// 获取ID:
Uri uri = Uri.prase(content://com.example.ContentProvider_name/table_name/10)
int id = ContentUris.parseId(uri);
//获取表名和id
Uri uri = Uri.prase(content://com.example.ContentProvider_name/table_name/id)
string table_name = uri.getPathSegments(uri).get(0) 得到table_name
int id = uri.getPathSegments(uri).get(1) 得到id;
自定义ContetnProvider:
4:ContentProvider提供器的实现及使用:
1:创建ContetnProvider:
//ContentProvider是一个抽象类;需要声明一个类继承该抽象类,并全部实现其六个方法
Public class MyProvider extends ContetnProvider{
/**
* 在通过ContetnResolver访问该内容提供器的时候才会调用;
* 返回true表示初始化成功,返回false表示初始化失败;
*/
public boolean onCreat(){
return true;
}
/**
* uri 确定要操作哪一张表
* projection 确定查询那些列
* selection 类似于where条件
* selectionArgs 条件参数
* sortOrder 排序
* discription 该方法供外部应用执行查询操作获取数据,返回Cursor对象
*/
Public Uri query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
/**
* uri 确定要操作哪一张表
* selection 类似于where条件
* selectionArgs 条件参数
* 该方法供外部应用删除数据,返回被删除的行数
*/
public int delete(Uri uri, String selection, String[] selectionArgs):
/**
* uri 确定要操作哪一张表
* values 要更新的数据
* selection 类似于where条件
* selectionArgs 条件参数
* 该方法供外部应用更新数据;返回受影响的行数
*/
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs){}
/**
* uri 确定要操作哪一张表
* values 要插入的数据
* 该方法供外部应用向ContentProvider填入数据;操作成功后返回一个URI,表示这条新纪录
*/
public Uri insert(Uri uri,ContentValues values){};
/**
* discription 供外部应用程序获取URI的MIME类型
* 如果操作的数据属于集合类型,那么MIME类型字符串应该以vnd.android.cursor.dir/开头
* 如果要操作的数据属于非集合类型数据,那么MIME类型字符串应该以vnd.android.cursor.item/开头,
*/
public String getType(){}
}
1:对于以上几个方法必须都要有实现;
2:增删改查以及获取uri类型的方法中都要通过UriMatcher判断之后操作;
3:ContentProvider只负责实现操作数据的具体方法,对数据的操作则是通过ContetnResolver来实现的:具体如下:
通过ContentResolver来操作数据:
1:创建ContentResolver实例:
1:ContentResolver contextResolver = context.getContentResolver();
2:创建uri:
//创建uri的目的就是为了找到目标ContentProvider,并传入需要操作的表名;在sqlite中则是直接传入表名的;
Uri uri = Uri.prase(content://com.example.ContentProvider_name/table_name);
3:使用ContentResolver进行数据的增删改查;
ContetnResolver提供的CURD方法和ContetnProvider提供的方法是一样的;
插入一条数据:insert(Uri uri,ContentValues values)
删除数据:delete(Uri uri, String selection, String[] selectionArgs)
更新一条数据:update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
查新数据:query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
????Contetnprovider的监听问题
????Contetnprovider的权限问题
4:监听ContentProvider的变化:
1:ContentResolver cr = getContentResolver();
2:cr.ontifyChange(uri,null);
3:对于需要监听的访问者:
1:当数据发生变化的时候就会调用ContentObserver的onChange()方法
2:ContentResolver cr = getContentResolver();
cr.registerContentObserver(uri,true,new MyObserver(new Handler()));
public class MyObserver extends ContentObserver{
public MyObserver (Handler handler){
super(Handler);
}
public onChange(Boolean change){
if(change == true){
//处理代码;
}
}
}
6:使用ContentResolver访问系统数据:
1:获取联系人信息:
注:ContactsContract.CommonDataKinds.Phone:是对联系人操作所封装的类:通过调用一系列常量可以获取具体字段的值;
string sql = 'ContactsContract.CommonDataKinds.Phone';
Cursor cursor = getContentResolver().query(sql+CONTENT_URI,NULL,NULL,NULL,NULL);
while(cursor.moveToNext()){
//获取联系人姓名
string user_name = cursor.getString(cursor.getColumnIndex(sql+DISPLAY_NAME));
//获取联系人号码:
string user_name = cursor.getString(cursor.getColumnIndex(sql+NUMBER));
}
1:查看联系人存储数据库:
http://www.cnblogs.com/luxiaofeng54/archive/2011/03/15/1985183.html
2:联系人信息获取:
http://www.cnblogs.com/3dant/archive/2010/12/08/1900634.html
常见的常量:
NUMBER:联系人号码
DSIPLAY_NAME:联系人姓名;
1:创建Uri:
Uri getSystenData = Uri.prase("content://media/internal/images");
一般只需要指定到表名就可以了,具体的行,字段等在查询函数中设置;
例如以下uri:
content://media/internal/images 这个URI将返回设备上存储的所有图片
content://contacts/people/ 这个URI将返回设备上的所有联系人信息
content://contacts/people/45 这个URI返回单个结果(联系人信息中ID为45的联系人记录)
实例:
1:自定义ContentProvider,并通过ContentResolver操作;
2:通过ContentResolver操作系统数据(电话薄)