1、为什么使用内容提供者
内容提供者是应用程序为了给其他应用程序提供访问数据库中数据的接口。
2、编写内容提供者
步骤:
1.在工程中添加一个内容提供者的类,继承contentprovider这个父类,在oncreate方法得到数据库的实例对象;
2.在清单文件中配置内容提供者,注意需要指定主机名和exported属性;
3.在内容提供者类中添加匹配器,实现增删改查的方法;
package account.contentprovider;
import account.db.AccountOpenHelper;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
public class AccountContentProvider extends ContentProvider {
private static final int INSERT = 0;
private static final int DELETE = 1;
private static final int QUERY = 2;
private static final int UPDATE = 3;
private static final int QUERY_ID = 4;
private static final int UPDATE_ID = 5;
private SQLiteDatabase db;
//NO_MATCH :当uri没有匹配成功时返回这个值
private static UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static{
//第一个参数:主机名,与清单文件中的主机名一样
//第二个参数:访问uri的路径
//第三个参数:匹配码,匹配成功时返回这个值
//content://account.contentprovider.AccountContentProvider/insert
uriMatcher.addURI("account.contentprovider.AccountContentProvider", "insert", INSERT);
uriMatcher.addURI("account.contentprovider.AccountContentProvider", "delete", DELETE);
uriMatcher.addURI("account.contentprovider.AccountContentProvider", "query", QUERY);
uriMatcher.addURI("account.contentprovider.AccountContentProvider", "query/#", QUERY_ID);
uriMatcher.addURI("account.contentprovider.AccountContentProvider", "update", UPDATE);
uriMatcher.addURI("account.contentprovider.AccountContentProvider", "update/#", UPDATE_ID);
}
/**
* 在内容提供者对象被创建后用来实例化对象的
*/
@Override
public boolean onCreate() {
AccountOpenHelper helper = new AccountOpenHelper(getContext());
db = helper.getWritableDatabase();
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
if(uriMatcher.match(uri) == QUERY_ID){
String[] uris = uri.toString().split("/");
String id = uris[uris.length-1];
//从数据库中查询数据
Cursor cursor = db.query("account", projection, "_id=?", new String[]{id}, null, null, null);
return cursor;
}else if(uriMatcher.match(uri) == QUERY){
//从数据库中查询数据
Cursor cursor = db.query("account", projection, selection, selectionArgs, null, null, null);
return cursor;
}else{
System.out.println("=======错误的path=========");
Cursor cursor = db.query("account", projection, selection, selectionArgs, null, null, null);
return cursor;
}
}
@Override
public String getType(Uri uri) {
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
// uri: 形式content://account.contentprovider.AccountContentProvider/insert
//匹配用户是否执行插入操作
if(uriMatcher.match(uri)== INSERT){
System.out.println("匹配成功..........");
db.insert("account", null, values);
}else{
System.out.println("不匹配..........");
}
return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
if(uriMatcher.match(uri)== DELETE){
int num = db.delete("account", selection, selectionArgs);
System.out.println("num=="+num);
return num;
}
return 0;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
if(uriMatcher.match(uri)== UPDATE){
db.update("account", values, selection, selectionArgs);
}else if(uriMatcher.match(uri)== UPDATE_ID){
String[] uris = uri.toString().split("/");
String id = uris[uris.length-1];
db.update("account", values, "_id=?", new String[]{id});
}
return 0;
}
}
清单文件:
<!-- 从4.1的版本开始,必须制定这个数据 android:exported="true" ,否则其他应用程序没有权限访问它-->
<provider android:name="account.contentprovider.AccountContentProvider"
android:authorities="account.contentprovider.AccountContentProvider"
android:exported="true" />
3、内容提供者工作的原理
在创建内容提供者时在清单文件中指定了主机名,这个主机名唯一标识一个内容提供者,在代码中添加了匹配的路径.在其他应用程序中使用内容提供者解析器操作内容提供者时,需要指定uri,这个uri指定了需要访问的内容提供者.内容提供者会判断用户传递过来的uri是否合法,如果不合法就不执行相应的操作,否则执行.
4、内容提供者的使用场景
当需要操作另外一个工程中的数据库的数据时,需要使用内容提供者解析器操作内容提供者操作数据库的数据;
5、内容提供者uri的写法
content://主机名/路径
content://主机名/路径/#(记录的id);
content://account.contentprovider.AccountContentProvider/query/11
如果用户传递的uri中的路径中包含内容提供者注册的路径的字符,是可以匹配到的;
解析器调用内容提供者时 必须指定了正确的主机名;