内容提供器是一种用于不同程序间实现数据共享的功能,使用内容提供器是Android中实现跨程序共享数据的标准方式。
内容提供器的用法分两种,一种是创建内容提供器给其它程序提供数据访问的接口,另一种是读取和操作其它程序中的数据。
访问其它程序的数据要借助使用 ContentResolver 类,可以通过 Context 中的 getContentResolver() 获取实例。其中有一系列的方法进行 CRUD 操作,和SQLiteDatabase中的方法类似,都是通过insert()、update()、delete()、query()进行的,只是在参数上有些差别。在SQLiteDatabase中的CRUD都接收表名参数,而 ContentResolver 中是用一个 Uri 参数代替,称为内容URI。它给内容提供器中的数据建立了唯一标识符。内容URI主要由 authority 和 path 组成。authority 是对不同应用程序作区分,一般采用 程序包名+.provider 来命名,path 是用于对同一程序中的不同表来区分的,通常是加在 authority 后面。内容URI的协议声明是 content:// 。(假设某个程序包名为com.example.xxx,数据库里有一张表table1,那么内容URI为 content://com.example.xxx.provider/table1,如果还要查询其中id为1的数据,那么内容URI为content://com.example.xxx.provider/table1/1)
通配符
*:表示匹配任意长度的任意字符
#:表示匹配任意长度的数字
所以在上述假设中能匹配任意表的内容URI为 content://com.example.xxx.provider/*
匹配table1表中的任意一行数据的内容URI为 content://com.example.xxx.provider/table1/#
ContentResolver 的insert()、update()、delete()、query()方法
1.Uri insert(Uri url, ContentValues values)
url:要插入表的url
values:插入的值
getContentResolver().insert(uri, values);
最后返回的结果是新创建的行的URL
2.int update(Uri uri, ContentValues values, String where, String[] selectionArgs)
uri:要修改表的URI
values:新的属性值,key是属性的列名,value为null表示移除一个存在的属性值
where:在更新前适用于行的一个过滤器,相当于SQL中的where子句
selectionArgs:上一个参数的占位符对应值
getContentResolver().update(uri, values, null, null);
最后返回的结果是更新的行数
3.int delete(Uri url, String where, String[] selectionArgs)
url:要删除行的url
where:在删除前适用于行的一个过滤器,相当于SQL中的where子句
selectionArgs:上一个参数的占位符对应值
getContentResolver().delete(uri, null, null);
最后返回的结果是删除的行数
4.Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
uri:某一应用中具体的表
projection:具体的列名,null表示所有列,但是用null效率低
selection:过滤返回的行,SQL中WHERE子句,null返回查询uri中的所有行
selectionArgs:上一个参数的占位符对应值
sortOrder:查询结果的排列方式,对应SQL中ORDER BY子句,null表示默认方式
getContentResolver().query(uri, null, null, null, null);
最后返回结果为Cursor对象,然后进行遍历即可,代码如下:
if (cursor != null) {
while (cursor.moveToNext()) {
String column = cursor.getString(cursor.getColumnIndex("column"));
// ……
}
cursor.close();
}
首先点击New->Other->Content Provider,弹出一个界面。URI Authorities 可以使用 程序包名+.provider 。Exported 表示是否允许外部程序访问该内容提供器,Enabled 表示是否启用该内容提供器。ContentProvider 类中有6个抽象方法需要重写,分别是 onCreate()、insert()、update()、delete()、query()、getType()。
ContentProvider 的onCreate()、insert()、update()、delete()、query()、getType()
1.boolean onCreate()
创建和升级数据库,返回true表示加载成功,false表示失败
2.Uri insert(Uri uri, ContentValues values)
uri:插入请求的uri,不能为空
values:插入的值,不能为空
返回值表示新创建的项目的URI值
3.int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
uri:要查询的uri
values:更新的数据,不能为空
selection:与要更新的行匹配的过滤器,可选
selectionArgs:上一个参数的占位符对应值
返回值表示受影响的行的数量
4.int delete(Uri uri, String selection, String[] selectionArgs)
uri:要查询的完整URI
selection:当删除时适用于某行的可选约束
selectionArgs:上一个参数的占位符对应值
返回值表示受影响的行的数量
5.Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder);
uri:要查询的URI
projection:要放入cursor中的列,如果为null,那么所有列都被包括
selection:适用于过滤时行的选择,如果为null,那么所有行都被包括
selectionArgs:上一个参数的占位符对应值
sortOrder:每一行在cursor中的排列,null表示默认
返回值表示一个Cursor对象或者为null
6.String getType(Uri uri)
uri:要查询的URI
返回值表示一个 MIME型的字符串 或者 null
一个内容URI的MIME字符串由3部分组成:
1.以 vnd 开头。
2.内容URI以路径结尾,后接.android.cursor.dir/,以id结尾,后接.android.cursor.item/
3.最后接vnd.
在上面几个方法中,除了 onCreate() 外,参数中都包含Uri的参数,我们要对Uri参数进行解析,分析其中要访问的表和数据。这时候可以借助 UriMatcher 这个类来实现匹配内容URI的功能。UriMatcher 中提供了 addURI(String authority, String path, int code) 方法,第一个参数表示要匹配的authority,第二个参数表示要匹配的path,第三个参数必须大于等于0,表示一个自定义的code。当调用UriMatcher中的 match(Uri uri) 时,就可以判断访问哪个表中的具体数据。
创建内容提供器示例如下(其中的数据库来自于 https://blog.csdn.net/myCSDN1997/article/details/83928838 中的例子)
public class MyProvider extends ContentProvider {
public static final int TABLE1_DIR = 0;
public static final int TABLE1_ITEM = 1;
public static final int TABLE2_DIR = 2;
public static final int TABLE2_ITEM = 3;
public static final String AUTHORITY = "com.example.xxx.provider";
private static UriMatcher uriMatcher;
private MySQLiteOpenHelper dbHelper;
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(AUTHORITY, "table1", TABLE1_DIR);
uriMatcher.addURI(AUTHORITY, "table1/#", TABLE1_ITEM);
uriMatcher.addURI(AUTHORITY, "table2", TABLE2_DIR);
uriMatcher.addURI(AUTHORITY, "table2/#", TABLE2_ITEM);
}
@Override
public boolean onCreate() {
dbHelper = new MySQLiteOpenHelper(getContext(),"College.db",null,2);
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteDatabase db = dbHelper.getReadableDatabase();
Cursor cursor = null;
switch (uriMatcher.match(uri)) {
case TABLE1_DIR:
// 查询TABLE1中所有数据
cursor = db.query("Table1", projection, selection, selectionArgs,
null, null, sortOrder);
break;
case TABLE1_ITEM:
// 查询TABLE1中单条数据
String id = uri.getPathSegments().get(1);
cursor = db.query("Table1", projection, "id=?", new String[]{id},
null, null, sortOrder);
case TABLE2_DIR:
// 查询TABLE2中所有数据
// ……
break;
case TABLE2_ITEM:
// 查询TABLE2中单条数据
// ……
break;
default:
}
return cursor;
}
// ……
// 其余4个抽象方法也是类似的。
}
接下来就可以从其它程序中来访问上面那个程序中对应的数据。
1.创建一个新的项目。
2.通过uri进行相应的CRUE操作,具体可以看 一.访问其它程序的数据 中的内容