ContentResolver
使用内容提供器是Android实现跨程序共享数据的标准方式。
基本用法
这里要访问的是通讯录,里面已经有一个系统自己的ContentProvider
数据查询无非是要最终得到Cursor对象并遍历,跨程序得到Cursor,就是需要用到ContentResolver了
例如:ContactsTest
得到系统通讯录的查询结果
Cursor cursor = getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
null,
null,
null);
第一个参数是一个Uri对象,ContentResolver就是通过这种方式来跨程序访问资源,这个Uri的String形式为:
协议名://包名.provider//表名
content://com.jackie.app.provider//table1
Uri.parse(String uri)//将字符串转化为Uri对象
自己定义ContentProvider
系统的通讯录之所以可以被访问到,因为里面有一个它的ContentProvider,那么如果我们自己的程序,例如之前我的DatabaseTest项目里的数据库,其他程序要对它进行CRUD,则需要在DatabaseTest项目里自己定义一个ContentProvider
package com.jackie.databasetest;
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;
import android.support.annotation.Nullable;
/**
* Created by Law on 2015/11/18.
*/
public class DatabaseProvider 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.jackie.databasetest.provider";
private static UriMatcher uriMatcher;
private MyDatabaseHelper myDatabaseHelper;
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(AUTHORITY, "book", BOOK_DIR);
uriMatcher.addURI(AUTHORITY, "book/#", BOOK_ITEM);
uriMatcher.addURI(AUTHORITY, "category", CATEGORY_DIR);
uriMatcher.addURI(AUTHORITY, "category/#", CATEGORY_ITEM);
}
@Override
public boolean onCreate() {
myDatabaseHelper = new MyDatabaseHelper(getContext(), "book.db", null, 2);
return true;
}
@Nullable
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
Cursor cursor = null;
SQLiteDatabase db = myDatabaseHelper.getReadableDatabase();
switch (uriMatcher.match(uri)) {
case BOOK_DIR:
cursor = db.query("book", projection, selection, selectionArgs, null, null, sortOrder);
break;
case BOOK_ITEM:
//比如:content://"+AUTHORIY+"/book/1",
//getPathSegments() 得到/book/1
//get(1)得到1
String bookId = uri.getPathSegments().get(1);
cursor = db.query("book", projection, "id=?", new String[]{bookId}, null, null, sortOrder);
break;
case CATEGORY_DIR:
cursor = db.query("category", projection, selection, selectionArgs, null, null, sortOrder);
break;
case CATEGORY_ITEM:
String categoryId = uri.getPathSegments().get(1);
cursor = db.query("category", projection, "id=?", new String[]{categoryId}, null, null, sortOrder);
break;
default:
break;
}
return cursor;
}
@Nullable
@Override
public String getType(Uri uri) {
switch (uriMatcher.match(uri)) {
case BOOK_DIR:
return "vnd.android.cursor.dir/vnd.com.jackie.databasetest.provider.book";
case BOOK_ITEM:
return "vnd.android.cursor.item/vnd.com.jackie.databasetest.provider.book";
case CATEGORY_DIR:
return "vnd.android.cursor.dir/vnd.com.jackie.databasetest.provider.category";
case CATEGORY_ITEM:
return "vnd.android.cursor.item/vnd.com.jackie.databasetest.provider.category";
}
return null;
}
@Nullable
@Override
public Uri insert(Uri uri, ContentValues values) {
SQLiteDatabase db = myDatabaseHelper.getWritableDatabase();
Uri uriReturn = null;
switch (uriMatcher.match(uri)) {
case BOOK_DIR:
long rowidBook = db.insert("book", null, values);
uriReturn = uri.parse("content://" + AUTHORITY + "/book/" + rowidBook);
break;
case BOOK_ITEM:
break;
case CATEGORY_DIR:
long rowidCategory = db.insert("category", null, values);
uriReturn = uri.parse("content://" + AUTHORITY + "/category/" + rowidCategory);
break;
case CATEGORY_ITEM:
break;
default:
break;
}
return uriReturn;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int deleteRow = 0;
SQLiteDatabase db = myDatabaseHelper.getWritableDatabase();
switch (uriMatcher.match(uri)) {
case BOOK_DIR:
deleteRow = db.delete("book", selection, selectionArgs);
break;
case BOOK_ITEM:
//比如:content://"+AUTHORIY+"/book/1",
//getPathSegments() 得到/book/1
//get(1)得到1
String bookId = uri.getPathSegments().get(1);
deleteRow = db.delete("book", "id=?", new String[]{bookId});
break;
case CATEGORY_DIR:
deleteRow = db.delete("category", selection, selectionArgs);
break;
case CATEGORY_ITEM:
String categoryId = uri.getPathSegments().get(1);
deleteRow = db.delete("category", "id=?", new String[]{categoryId});
break;
default:
break;
}
return deleteRow;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
int updateRow = 0;
SQLiteDatabase db = myDatabaseHelper.getWritableDatabase();
switch (uriMatcher.match(uri)) {
case BOOK_DIR:
updateRow = db.update("book", values, selection, selectionArgs);
break;
case BOOK_ITEM:
//比如:content://"+AUTHORIY+"/book/1",
//getPathSegments() 得到/book/1
//get(1)得到1
String bookId = uri.getPathSegments().get(1);
updateRow = db.update("book", values, "id=?", new String[]{bookId});
break;
case CATEGORY_DIR:
updateRow = db.update("category", values, selection, selectionArgs);
break;
case CATEGORY_ITEM:
String categoryId = uri.getPathSegments().get(1);
updateRow = db.update("category", values, "id=?", new String[]{categoryId});
break;
default:
break;
}
return updateRow;
}
}
记得在配置文件中,声明android:exported="true"
<provider
android:name="com.jackie.databasetest.DatabaseProvider"
android:authorities="com.jackie.databasetest.provider"
android:exported="true" />
然后新建另外的项目,来访问这个数据库
package com.jackie.providertest;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private String newId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btnAdd).setOnClickListener(this);
findViewById(R.id.btnDelete).setOnClickListener(this);
findViewById(R.id.btnQuery).setOnClickListener(this);
findViewById(R.id.btnUpdate).setOnClickListener(this);
}
@Override
public void onClick(View v) {
Uri uriDir = Uri.parse("content://com.jackie.databasetest.provider/book");
Uri uriItem = Uri.parse("content://com.jackie.databasetest.provider/book/" + newId);
switch (v.getId()) {
case R.id.btnAdd:
ContentValues book = new ContentValues();
book.put("name", "无声告白");
book.put("price", 17.15);
book.put("pages", 290);
book.put("author", "伍绮诗");
Uri newUri = getContentResolver().insert(uriDir, book);
newId = newUri.getPathSegments().get(1);
break;
case R.id.btnQuery:
Cursor cursor = getContentResolver().query(uriDir, null, null, null, null);
if (cursor != null) {
while (cursor.moveToNext()) {
String name = cursor.getString(cursor.getColumnIndex("name"));
String author = cursor.getString(cursor.getColumnIndex("author"));
double price = cursor.getDouble(cursor.getColumnIndex("price"));
int pages = cursor.getInt(cursor.getColumnIndex("pages"));
Log.v("jackie", "name is" + " " + name);
Log.v("jackie", "author is" + " " + author);
Log.v("jackie", "price is" + " " + price);
Log.v("jackie", "pages is" + " " + pages);
}
}
break;
case R.id.btnUpdate:
ContentValues bookNew = new ContentValues();
bookNew.put("name", "年少荒唐");
bookNew.put("price", 18.00);
bookNew.put("pages", 323);
bookNew.put("author", "朱炫");
getContentResolver().update(uriItem, bookNew, null, null);
break;
case R.id.btnDelete:
getContentResolver().delete(uriItem, null, null);
break;
}
}
}
分别在外部程序对DatabaseTest中的数据库进行CRUD操作,Log如下:
插入后:
11-18 15:05:29.275 22065-22065/? V/jackie: name is 无声告白
11-18 15:05:29.275 22065-22065/? V/jackie: author is 伍绮诗
11-18 15:05:29.275 22065-22065/? V/jackie: price is 17.15
11-18 15:05:29.275 22065-22065/? V/jackie: pages is 290
更新后:
11-18 15:05:50.590 22065-22065/? V/jackie: name is 年少荒唐
11-18 15:05:50.590 22065-22065/? V/jackie: author is 朱炫
11-18 15:05:50.590 22065-22065/? V/jackie: price is 18.0
11-18 15:05:50.590 22065-22065/? V/jackie: pages is 323