Content Provider(内容提供者)是Android四大组件之一,其为存储和获取数据提供统一的接口。使不同的应用程序之间可以共享数据。其以Uri的形式对外提供数据的访问操作接口,而其他应用则通过ContentResolver类对象根据Uri去访问指定的数据。当某个应用通过Content Provider提供了自己的数据接口,不管该应用程序是否启动,其他程序都可以通过该接口来操作其内部的数据。
Android为我们提供了多种ContentProvider,比如通讯录、多媒体等,当然我们也可以创建自己的ContentProvider。
URI是统一资源标识符,是一个用于标识某一互联网资源名称的字符串。 该种标识允许用户对任何(包括本地和互联网)的资源通过特定的协议进行交互操作。URI由包括确定语法和相关协议的方案所定义。有三个组成部分:访问资源的命名机制、存放资源的主机名、资源自身的名称。
比如:
URI格式为 scheme://authority/path
举例为 content://com.myapp.mycontentprovider/tablename/id
①scheme为固定前缀: content://
②Authority是一个ContentProvider的唯一标识,外部调用者可以根据这个标识来找到它: com.myapp.mycontentprovider
③path表示我们要操作的数据,可以是表名,也可以是文件名: tablename
④path后也可以加上id或name,定位到某一行数据,不加的话就是表中所有数据
URI的两个工具类:
UriMatcher:用于匹配Uri,匹配后返回结果码。代码如下:
Uri uri= Uri.parse("content://com.myapp.mycontentprovider/tablename");
/* 自定义匹配码 */
final int NOPARAM = 1;
final int PARAM = 2;
//常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码
UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
//如果用match()方法匹配content://com.myapp.mycontentprovider/tablename,返回匹配码为NOPARAM
// 注册uri
uriMatcher .addURI("com.myapp.mycontentprovider", "tablename", NOPARAM);
//如果用match()方法匹配content://com.com.myapp.mycontentprovider/tablename/id路径,返回匹配码为PARAM
uriMatcher.addURI("com.myapp.mycontentprovider", "tablename/#", PARAM);
// #号为数字通配符
switch (uriMatcher.match(uri)) {
case NOPARAM:
//
break;
case PARAM:
//
break;
default:
//
break;
}
ContentUris:用于操作Uri路径后面的Id部分。代码如下:
// 给uri加上id
Uri uri = Uri.parse("content://com.myapp.mycontentprovider/tablename");
Uri resultUri = ContentUris.withAppendedId(uri, 1);
//生成后的Uri为:content://com.myapp.mycontentprovider/tablename/1
// 获取uri后的id
Uri uri = Uri.parse("content://com.myapp.mycontentprovider/tablename/1")
long id = ContentUris.parseId(uri);
// id为1
创建自己的Content Provider首先继承android.content.ContentProvider类,再重写它的几个方法。主要是对数据的增删查改方法,代码如下:
import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
public class MyContentProvider extends ContentProvider {
public MyContentProvider() {
}
//删除数据
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// Implement this to handle requests to delete one or more rows.
throw new UnsupportedOperationException("Not yet implemented");
}
//返回MIME类型的字符串
@Override
public String getType(Uri uri) {
// TODO: Implement this to handle requests for the MIME type of the data
// at the given URI.
throw new UnsupportedOperationException("Not yet implemented");
}
//插入数据
@Override
public Uri insert(Uri uri, ContentValues values) {
// TODO: Implement this to handle requests to insert a new row.
throw new UnsupportedOperationException("Not yet implemented");
}
//初始化
@Override
public boolean onCreate() {
// TODO: Implement this to initialize your content provider on startup.
return false;
}
//查询数据
@Override
public Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) {
// TODO: Implement this to handle query requests from clients.
throw new UnsupportedOperationException("Not yet implemented");
}
//更新数据
@Override
public int update(Uri uri, ContentValues values, String selection,String[] selectionArgs) {
// TODO: Implement this to handle requests to update one or more rows.
throw new UnsupportedOperationException("Not yet implemented");
}
}
在创建完自己的ContentProvider后,要到AndroidManifest.xml文件进行注册。代码如下:
<provider android:name="com.myapp.MyContentProvider" android:authorities="com.myapp.mycontentprovider" android:enabled="true" android:exported="true">
</provider>
在别的应用中,我们使用Content Resolver类来获取和操作ContentProvider提供的数据。ContentResolver类中提供了和ContentProvider类中签名一样的方法。代码如下:
uri = Uri.parse("content://com.test.mycontentprovider/test");
// 获取ContentResolver对象
ContentResolver contentResolver = getContentResolver();
// 插入数据
ContentValues contentValues = new ContentValues();
contentValues.put("name", "ResolverTest");
Uri uri = contentResolver.insert(uri, contentValues);
Toast.makeText(MainActivity.this, uri.toString(), Toast.LENGTH_LONG).show();
// 查找所有数据,contentResolver.query返回的是一个结果集
cursor = contentResolver.query(uri, null, null,null, null);
while(cursor.moveToNext()){
int name = cursor.getColumnIndex("name");
Toast.makeText(MainActivity.this, cursor.getString(name), Toast.LENGTH_SHORT).show();
}
// 查找id为1的数据
cursor = contentResolver.query(uri, null, "_ID=?", new String[] { "1" }, null);
//这里要调用cursor.moveToFirst将游标移动到第一条数据
if (cursor.moveToFirst() == false) {
// Cursor为空
return;
}
int name = cursor.getColumnIndex("name");
Toast.makeText(MainActivity.this, cursor.getString(name), Toast.LENGTH_LONG).show();
// 更新数据
contentValues.put("name", "Resolver_2");
uri = contentResolver.update(uri, contentValues, "_ID=?", new String[]{"1"});
Toast.makeText(MainActivity.this, "updated"+":"+uri, Toast.LENGTH_LONG).show();
// 删除id为1的数据
contentResolver.delete(uri, "_ID=?", new String[]{"1"});
cursor.close();