1.Contentprovider(组件)内容提供者:
对外共享数据使用,可以把任意类型的数据进行对外共享;如:xml、数据库、txt等;好处是统一了数据对外的访问方式
ContentProvider(内容提供者)的scheme已经由Android规定,scheme为:content://主机名(或Authority)用于唯一标识这个
ContentProvider,外部调用这个可以根据这个标识来找到它。
路径(Path)可以用来表示我们要操作的数据,路径的应用根据业务而定
要操作user表中的id为1的记录,可以构建路径:/user/1
要操作user表中的id为1的记录的age字段,可以构建路径:/user/1/age
要操作user表中的所有记录,可以构建路径:/user
测试:
对外共享数据使用,可以把任意类型的数据进行对外共享;如:xml、数据库、txt等;好处是统一了数据对外的访问方式
ContentProvider(内容提供者)的scheme已经由Android规定,scheme为:content://主机名(或Authority)用于唯一标识这个
ContentProvider,外部调用这个可以根据这个标识来找到它。
路径(Path)可以用来表示我们要操作的数据,路径的应用根据业务而定
要操作user表中的id为1的记录,可以构建路径:/user/1
要操作user表中的id为1的记录的age字段,可以构建路径:/user/1/age
要操作user表中的所有记录,可以构建路径:/user
如果要操作文件、xml或其它数据,可以这样命名路径:要操作xml文件中user节点下的age字段,可以构建路径:/user/age
使用方法,在使用ContentProvider时首先需要继承ContentProvider,因为ContentProvider是组件需要在应用清单文件中进行配置
示例:
import cn.kafei.service.DBOpenHelper;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
public class UserProvider extends ContentProvider {
private DBOpenHelper dbOpenHelper;//打开数据库
private static final UriMatcher MATCHER = new UriMatcher(UriMatcher.NO_MATCH);//添加供匹配的URI
private static final int USERS = 1;
private static final int USER = 2;
static {
// 第一个参数:主机名,也就是在清单文件配置的provider的android:authorities
// 第二参数:表示要匹配那个路径
// 第三个参数:表示匹配码的标识,如果匹配成功就返回
MATCHER.addURI("cn.kafei.provides.userprovider", "user", USERS);//匹配user表中的所有记录
// #:表示数字,*号表示所有字符
MATCHER.addURI("cn.kafei.provides.userprovider", "user/#", USER);//根据ID进行匹配
}
/**
* 当内容提供者的实例被创建出来之后被调用,只执行一次
*/
@Override
public boolean onCreate() {
dbOpenHelper = new DBOpenHelper(this.getContext());
return true;
}
/**
* 返回你目前要操作的数据的内容类型 如:txt:plain/text html:html/text
*/
@Override
public String getType(Uri uri) {
switch (MATCHER.match(uri)) {
case 1:
return "vnd.android.cursor.dir/user";
case 2:
return "vnd.android.cursor.item/user";
default:
throw new IllegalArgumentException("this is Unknown Uri:" + uri);
}
}
/**
* 可以供外部的应用往内容提供者插入数据 values:用来存放各个字段的值
*/
@Override
public Uri insert(Uri uri, ContentValues values) {
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
switch (MATCHER.match(uri)) {
case 1:
// 如果主键是整型,那么这个行号就等于你的主键值
long rowid = db.insert("user", "name", values);
// content://cn.kafei.provides.userprovider/user/1
// Uri
// insertUri=Uri.parse("content://cn.kafei.provides.userprovider/user/"+rowid);
Uri insertUri = ContentUris.withAppendedId(uri, rowid);
return insertUri;
default:
throw new IllegalArgumentException("this is Unknown Uri:" + uri);
}
}
/**
* 允许外部的应用删除内容提供者中的数据
*/
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
int num = 0;
switch (MATCHER.match(uri)) {
case 1:
num = db.delete("user", selection, selectionArgs);
break;
case 2:
long rowid = ContentUris.parseId(uri);// 从URI中获取传入的ID
String where = "id=" + rowid;
if (selection != null && !"".equals(selection.trim())) {
where += " and " + selection;
}
num = db.delete("user", where, selectionArgs);
break;
default:
throw new IllegalArgumentException("this is Unknown Uri:" + uri);
}
return num;
}
/**
* 允许外部的应用对内容提供者中的数据进行更新
*/
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
int num = 0;
switch (MATCHER.match(uri)) {
case 1:
num = db.update("user", values, selection, selectionArgs);
break;
case 2:
long rowid = ContentUris.parseId(uri);// 从URI中提取传入的ID
String where = "id=" + rowid;
if (selection != null && !"".equals(selection.trim())) {
where += " and " + selection;
}
num = db.update("user", values, where, selectionArgs);
break;
default:
throw new IllegalArgumentException("this is Unknown Uri:" + uri);
}
return num;
}
/**
* 可以供外部的应用查询内容提供者的数据
*/
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
switch (MATCHER.match(uri)) {
case 1:
return db.query("user", projection, selection, selectionArgs, null,
null, sortOrder);
case 2:
long rowid = ContentUris.parseId(uri);// 从URI中提取传入的ID
String where = "id=" + rowid;
if (selection != null && !"".equals(selection.trim())) {
where += " and " + selection;
}
return db.query("user", projection, where, selectionArgs, null,
null, sortOrder);
default:
throw new IllegalArgumentException("this is Unknown Uri:" + uri);
}
}
}
在应用清单文件中(application)标签内进行配置ContentProvider组件:
<!--android:name:表示ContentProvider的类名;android:authorities:表示主机名 ,主机名可以自定义,但是建议按照所提供的格式,以免引起重复-->
<provider
android:name=".UserProvider"
android:authorities="cn.kafei.provides.userprovider" >
</provider>
以上完成后就算ContentProvider配置完成
测试:
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.test.AndroidTestCase;
import android.util.Log;
public class AccessContentProviderTest extends AndroidTestCase {
private final String TAG="AccessContentProviderTest";
/**
* 测试插入
*/
public void testInsert()throws Exception{
Uri uri=Uri.parse("content://cn.kafei.provides.userprovider/user");//要操作的路径
ContentResolver resolver=this.getContext().getContentResolver();
ContentValues values=new ContentValues();
values.put("name", "ht896632");
values.put("age", "99");
values.put("amount", "1234000000");
resolver.insert(uri, values);
}
/**
* 测试删除
*/
public void testDelete()throws Exception{
Uri uri=Uri.parse("content://cn.kafei.provides.userprovider/user/23");
ContentResolver resolver=this.getContext().getContentResolver();
resolver.delete(uri, null, null);
}
/**
* 测试更新
*/
public void testUpdate()throws Exception{
Uri uri=Uri.parse("content://cn.kafei.provides.userprovider/user/22");
ContentResolver resolver=this.getContext().getContentResolver();
ContentValues values=new ContentValues();
values.put("name", "李宏涛");
resolver.update(uri, values, null, null);
}
/**
* 测试查询
*/
public void testQuery()throws Exception{
Uri uri=Uri.parse("content://cn.kafei.provides.userprovider/user");
ContentResolver resolver=this.getContext().getContentResolver();
Cursor cursor=resolver.query(uri, null, null, null, "id desc");
while(cursor.moveToNext()){
String name=cursor.getString(cursor.getColumnIndex("name"));
int id=cursor.getInt(cursor.getColumnIndex("id"));
Log.i(TAG, "ID:"+id+" name:"+name);
}
cursor.close();
}
}
注意:ContentProvider的注要作用是对外共享数据。
2.监听ContentProvider数据中的变化
思路:首先往ContentProvider中添加数据,然后通过其它应用监听ContentProvider中的数据变化。
添加数据方法(使用一个应用往ContentProvider中添加数据):
public void add(View view){
Uri uri=Uri.parse("content://cn.kafei.provides.userprovider/user");//要操作的路径
ContentResolver resolver=this.getContentResolver();
ContentValues values=new ContentValues();
values.put("name", "One");
values.put("age", "101");
values.put("amount", "9000");
resolver.insert(uri, values);
}
监听数据方法(放在一个应用的onCreate方法中,并且让这个应用保持在运行状态,否则监听不到):
Uri uri=Uri.parse("content://cn.kafei.provides.userprovider/user");//要操作的路径
//第一个参数:要监听的URI
//第二个参数:是否依赖
//第三参数:表示监听对象
this.getContentResolver().registerContentObserver(uri, true, new UserContentOberver(new Handler()));
//以上代码放在onCreate方法中,监听时,作为监听的应该必须启动
/**
* 监听数据方法
*/
private class UserContentOberver extends ContentObserver{
public UserContentOberver(Handler handler) {
super(handler);
}
//只能粗略的监听到数据是否发生变化
@Override
public void onChange(boolean selfChange) {
//select * from user order by id desc limit 1
Uri uri=Uri.parse("content://cn.kafei.provides.userprovider/user");//要操作的路径
Cursor cursor=getContentResolver().query(uri, null, null, null, "id desc");
if(cursor.moveToFirst()){
String name=cursor.getString(cursor.getColumnIndex("name"));
Log.i(TAG, name);
}
}
}
注:ContentProvider、添加数据方法、监听数据方法在三个不同的应用中,连接他们之前的就是一个URI:
content://cn.kafei.provides.userprovider/user