内容提供器主要用于在不同的应用程序之间实现数据共享的功能。他提供了一套完整的机制,允许一个程序访问另一个程序中的数据,同时还能保证被访数据的安全性。
ContentResolver
可以通过context .getContentResolver()方法获取该类的实例
同样的有CRUD的增删改查,不过查询的内容不是通过表名,而是通过URI
Uri
URI的标准写法是:content://com.example.app.provider/table1
得到URI之后,将之解析成Uri对象即可,解析方法如下
Uri uri =Uri.parse("URI")
然后就可以用这个Uri对象来查询table1中的数据了。代码如下:
Cursor cursor= getContentResolver().query(uri,projection,selection,selectionArgs,sortOrder)
query(方法参数) | 对应SQL部分 | 描述 |
---|---|---|
uri | from table_name | 指定查询的表名 |
projection | select columns1,columns2 | 指定查询的列名 |
selection | where column=value | 指定where的约束条件 |
selectionArgs | - | 为where中的占位符提供具体的值 |
orderBy | order by column1,column2 | 指定查询结果的排序方式 |
查询完成后,
if(cursor!=null){
while(cursor.moveToNext()){
String column1=cursor.getString(cursor.getColumnIndex(“column1”));
int column2=cursor.getInt(cursor.getColumnIndex(“column2”));
}
cursor.close();
}
增删改查和数据库差不多,只是操作主体不一样。就不再多说了。
权限:android.permission.READ_CONTACTS
主要代码:
private void readContact() {
Cursor cursor=null;
try{
//查询联系人数据
cursor=getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,null,null,null);
while(cursor.moveToNext()){
//获取联系人姓名
String name=cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
//获取联系人手机号
String number=cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
listStr.add(name +":"+number );//List<String>
}
}catch (NullPointerException e){
e.printStackTrace();
}finally {
if(cursor!=null){
cursor.close();
}
}
}
使用自己的提供器继承CotentProvider需要重写全部六个方法
public class MyProvider extends ContentProvider {
@Override
public boolean onCreate() { //通常在这里完成数据库的创建和升级等
return false;//返回true表示初始化成功(用ContentResolver尝试访问数据时,ContentProvider才会被初始化)
}
@Nullable
@Override //参数的含义可以参照上面的表格。
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
return null;
}
@Nullable
@Override
public String getType(Uri uri) { //根据传入的内容URI来返回相应的MIME类型。
return null;
}
@Nullable
@Override
public Uri insert(Uri uri, ContentValues values) {
return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return 0;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
return 0;
}
}
其他类似
很明显的,我们需要解析传入的URI:
content://com.example.app.provider/table1/1最后一个参数表示id为1
通配符:1.* 表示匹配任意长度的任意字符;2.# 表示匹配任意长度的数字。
然后再借助UriMatcher这个类来实现匹配内容URI的功能。
public static final int TABLE_DIR=0;
public static final int TABLE_ITEM=1;
private static UriMatcher uriMatcher;
static{
uriMatcher=new UriMatcher(UriMatcher.NO_MATCH);
//addURI参数分离“权限”、“路径”、“自定义代码”,当传入前面两个参数,会返回第三个代码,方便查询
uriMatcher.addURI("com.example.app.provider","table1",TABLE_DIR);
uriMatcher.addURI("com.example.app.provider","table1/#",TABLE_ITEM);
}
@Nullable
@Override //参数的含义可以参照上面的表格。
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
switch(uriMatcher.match(uri)){
case TABLE_DIR:
//查询所有
break;
case TABLE_ITEM:
//查询某个id数据
break;
}
return null;
}
一个内容URI所对应的MIME字符串主要由三部分组成,规定如下:
1、必须以vnd开头
2、如果内容URI以路径结尾,vnd后面要接android.cursor.dir/,如果内容URI以id结尾,则接android.cursor.item/
3、最后接上vnd..。
举个例子,
content://com.example.app.provider/table1对应的MIME类型是:
vnd.android.cursur.dir/vnd.com.example.app.provider.table1
content://com.example.app.provider/table1/1对应的MIME类型是:
vnd.android.cursur.item/vnd.com.example.app.provider.table1
然后可以在getType中根据query中的match方式,返回对应的MIME。
如上所诉,先创建一个MyDatabaseHelper,onCreate中添加book表的创建
Provider需要注册authorities是和下面访问用的AUTHORITY需要一致
<provider
android:authorities="com.example.tpout.myapplication.provider"
android:name="com.example.tpout.myapplication.MyDatabaseProvider"
android:exported="true"> <!-- 可以被其他应用访问-->
</provider>
然后实现MyContentProvider,对各方面的请求进行处理
public class MyDatabaseProvider extends ContentProvider {
public static final int BOOK_DIR=0;
public static final int BOOK_ITEM=1;
public static final int CATEGORY_DIR=2;
public static final int CATEGORY_ITEM=3;
public static final String AUTHORITY="com.example.tpout.myapplication.provider";
private static UriMatcher uriMatcher;
//在这里实例化数据库
private MyDatabaseHelper databaseHelper;
static {
uriMatcher=new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(AUTHORITY,"book",BOOK_DIR);
uriMatcher.addURI(AUTHORITY,"book/#",BOOK_ITEM);
}
@Override
public boolean onCreate() {
//创建数据库
databaseHelper=new MyDatabaseHelper(getContext(),"BookStore.db",null,1);
return true;
}
//查询的相关解析
@Nullable
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
SQLiteDatabase db=databaseHelper.getReadableDatabase();
Cursor cursor=null;
switch (uriMatcher.match(uri)){
case BOOK_DIR:
cursor=db.query("Book",projection,selection,selectionArgs,null,null,sortOrder);
break;
case BOOK_ITEM:
//getPathSegments讲URI权限之后的部分已“/”符号进行分割,放入字符串列表。0位为路径,1位为id
String bookId=uri.getPathSegments().get(1);
cursor=db.query("Book",projection,"id=?",new String[]{bookId},null,null,sortOrder);
break;
}
return cursor;
}
//获取MIME
@Nullable
@Override
public String getType(Uri uri) {
switch (uriMatcher.match(uri)){
case BOOK_DIR:
return "vnd.android.cursor.dir/vnd.com.example.tpout.myapplication.provider.book";
case BOOK_ITEM:
return "vnd.android.cursor.item/vnd.com.example.tpout.myapplication.provider.book";
}
return null;
}
//插入。
@Nullable
@Override
public Uri insert(Uri uri, ContentValues values) {
SQLiteDatabase db=databaseHelper.getWritableDatabase();
Uri uriReturn=null;
switch (uriMatcher.match(uri)){
case BOOK_DIR:
case BOOK_ITEM:
long newBookId=db.insert("Book",null,values);
uriReturn=Uri.parse("content://"+AUTHORITY+"/book/"+newBookId);
break;
default:
break;
}
return uriReturn;
}
//删除。
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
SQLiteDatabase db=databaseHelper.getWritableDatabase();
int deleteRows=0;
switch (uriMatcher.match(uri)){
case BOOK_DIR:
deleteRows=db.delete("Book",selection,selectionArgs);
break;
case BOOK_ITEM:
String booId=uri.getPathSegments().get(1);
deleteRows=db.delete("Book","id=?",new String[]{booId});
break;
default:
break;
}
return deleteRows;
}
//更新
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
SQLiteDatabase db=databaseHelper.getWritableDatabase();
int updateRows=0;
switch (uriMatcher.match(uri)){
case BOOK_DIR:
updateRows=db.update("Book",values,selection,selectionArgs);
break;
case BOOK_ITEM:
String booId=uri.getPathSegments().get(1);
updateRows=db.update("Book",values,"id=?",new String[]{booId});
break;
default:
break;
}
return updateRows;
}
}
最后在MainActivity中模拟读取数据
String newId;//用于记录添加的第几个数据
//添加
add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Uri uri=Uri.parse("content://com.example.tpout.myapplication.provider/book");
ContentValues values=new ContentValues();
values.put("name","A clash");
values.put("author","A cl");
values.put("pages",333);
values.put("price",2.85);
Uri newUri=getContentResolver().insert(uri,values);
newId=newUri.getPathSegments().get(1);
}
});
//查询
query.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Uri uri=Uri.parse("content://com.example.tpout.myapplication.provider/book");
Cursor cursor=getContentResolver().query(uri,null,null,null,null);
if(cursor!=null){
while(cursor.moveToNext()){
String name=cursor.getString(cursor.getColumnIndex("name"));
String author=cursor.getString(cursor.getColumnIndex("author"));
int pages=cursor.getInt(cursor.getColumnIndex("pages"));
double price=cursor.getDouble(cursor.getColumnIndex("price"));
Log.d("MainActivity","name :"+name);
Log.d("MainActivity","author :"+author);
Log.d("MainActivity","pages :"+pages);
Log.d("MainActivity","price :"+price);
}
cursor.close();
}
}
});
//更新
update.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Uri uri=Uri.parse("content://com.example.tpout.myapplication.provider/book/"+newId);
ContentValues values=new ContentValues();
values.put("name","a st");
values.put("pages",23);
values.put("price",22.0);
getContentResolver().update(uri,values,null,null);
}
});
//删除
delete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Uri uri=Uri.parse("content://com.example.tpout.myapplication.provider/book/"+newId);
getContentResolver().delete(uri,null,null);
}
});
}