Content Provider

ContentProvider 简介

ContentProvider 主要用于在不同的应用程序之间实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另一个程序中的数据,同时还能保证被访问数据的安全性。

实现各个应用程序之间的(跨应用)数据共享,比如联系人应用中就使用了ContentProvider,你在自己的应用中可以读取和修改联系人的数据,不过需要获得相应的权限。其实它也只是一个中间人,真正的数据源是文件或者SQLite等

内容提供器的用法一般有两种,一种是使用现有的内容提供器来读取和操作相应程序中的数据,另一种是创建自己的内容提供器把我们程序的数据提供外部接口访问。

访问其他程序中的数据

如 Android 自带的电话博、短信、媒体库等都提供了了对其数据访问的外部接口。

ContentResolver 用法

通过 Context 类中的 getContentResolver() 方法来获得 ContentResolver 类的实例,进而去访问内容提供器共享的数据。 ContentResolver 类中也提供了增删改查这些方法。这些方法接受一个 内容 URL 参数。

增删改查

URL 由权限(authority)和路径(path)两部分组成, 内容 URL 的标准格式:

content://com.nvgtor.app.provider/table1
协议声明         权限                路径
  1. query 方法

    Cursor cursor = getContentResolver().query(uri,//解析内容字符串后的Uri对象
        projection,//指定查询列名
        selection,//指定 where 的约束条件
        selectionArgs,//为 where 中的占位符提供具体值
        sortOrder//指定查询结果的排序方式
        );
    
  2. insert 方法

    ContentValues values = new ContentValues();
    values.put("column1", "nvgtor");
    getContentResolver().insert(uri, values);
    
  3. update 方法

    getContentResolver().update(uri, values, "column1 = ? and column2 = ?", new String[]{"text", "100"});
    
  4. delete 方法

    getContentResolver().delete(uri, "column2 = ?", new String[]{"100"});
    

读取联系人实例

android6.0 需动态请求读写联系人的权限

private void readContacts() {
    Cursor cursor = null;
    try {
        cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                null,
                null,
                null,
                null);
        if (cursor != null) {
            while (cursor.moveToNext()){
                String displayName = cursor.getString(
                        cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                String number = cursor.getString(
                        cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                concatList.add(displayName + "/n" + number);
            }
        } if (concatList != null) {
            adapter.notifyDataSetChanged();
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (cursor != null){
            cursor.close();
        }
    }
}

创建自己的内容提供器

通过继承 ContentProvider 来创建自己的内容提供器。在本地创建一个数据库,里面创建一张表Book,通过内容提供者可以来增删改查这张表

public class MyProvider 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 = "app.nvgtor.com.leanrning.provider";

public static UriMatcher uriMatcher;

private MyDatabaseHelper dbHelper;

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() {
    dbHelper = new MyDatabaseHelper(getContext(), "BookStore.db", null, 2);
    return true;
}

@Nullable
@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 BOOK_DIR:
            cursor = db.query("Book", projection, selection, selectionArgs,
                    null, null, sortOrder);
            break;
        case BOOK_ITEM:
            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 categorykId = uri.getPathSegments().get(1);
            cursor = db.query("Category", projection, "id = ?", new String[]{categorykId},
                    null, null, sortOrder);
            break;
        default:
            break;
    }

    return cursor;
}

/**
 * 用于获取 Uri 对象所对应的 MIME 类型
 * @param uri
 * @return
 */
@Nullable
@Override
public String getType(Uri uri) {
    switch (uriMatcher.match(uri)) {
        case BOOK_DIR:
            return "vnd.android.cursor.dir/vnd.app.nvgtor.com.leanrning.provider.book";
        case BOOK_ITEM:
            return "vnd.android.cursor.item/vnd.app.nvgtor.com.leanrning.provider.book";
        case CATEGORY_DIR:
            return "vnd.android.cursor.dir/vnd.app.nvgtor.com.leanrning.provider.category";
        case CATEGORY_ITEM:
            return "vnd.android.cursor.item/vnd.app.nvgtor.com.leanrning.provider.category";
    }
    return null;
}

@Nullable
@Override
public Uri insert(Uri uri, ContentValues values) {
    SQLiteDatabase db = dbHelper.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;
        case CATEGORY_DIR:
        case CATEGORY_ITEM:
            long newCategoryId = db.insert("Category", null, values);
            uriReturn = Uri.parse("content://" + AUTHORITY + "/category/" + newCategoryId);
            break;
        default:
            break;
    }
    return uriReturn;
}

@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
    SQLiteDatabase db = dbHelper.getWritableDatabase();
    int deleteRows = 0;
    switch (uriMatcher.match(uri)){
        case BOOK_DIR:
            deleteRows = db.delete("Book", selection, selectionArgs);
            break;
        case BOOK_ITEM:
            String bookId = uri.getPathSegments().get(1);
            deleteRows = db.delete("Book", "id = ?", new String[]{bookId});
            break;
        case CATEGORY_DIR:
            deleteRows = db.delete("Category", selection, selectionArgs);
            break;
        case CATEGORY_ITEM:
            String categoryId = uri.getPathSegments().get(1);
            deleteRows = db.delete("Category", "id = ?", new String[]{categoryId});
            break;
        default:
            break;
    }
    return deleteRows;
}

@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
    SQLiteDatabase db = dbHelper.getWritableDatabase();
    int updateRows = 0;
    switch (uriMatcher.match(uri)){
        case BOOK_DIR:
            updateRows = db.update("Book", values, selection, selectionArgs);
            break;
        case BOOK_ITEM:
            String bookId = uri.getPathSegments().get(1);
            updateRows = db.update("Book", values, "id = ?", new String[]{bookId});
            break;
        case CATEGORY_DIR:
            updateRows = db.update("Category", values, selection, selectionArgs);
            break;
        case CATEGORY_ITEM:
            String categoryId = uri.getPathSegments().get(1);
            updateRows = db.update("Category", values, "id = ?", new String[]{categoryId});
            break;
        default:
            break;
    }
    return updateRows;
}
}

在另一个程序:

public void onClick(View v) {
    switch (v.getId()){
        case R.id.add_data:
            Uri uri = Uri.parse("content://app.nvgtor.com.leanrning.provider/book");
            ContentValues values = new ContentValues();
            values.put("name", "A Clash of Kings");
            values.put("author", "George Martin");
            values.put("pages", 1040);
            values.put("price", 22.85);
            Uri newUri = getContentResolver().insert(uri, values);
            newId = newUri.getPathSegments().get(1);
            break;
        case R.id.query_data:
            Uri uri1 = Uri.parse("content://app.nvgtor.com.leanrning.provider/book");
            Cursor cursor = getContentResolver().query(uri1, 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(TAG, "book name is " + name);
                    Log.d(TAG, "book author is " + author);
                    Log.d(TAG, "book pages id " + pages);
                    Log.d(TAG, "book price is " + price);
                }
                cursor.close();
            }
            break;
        case R.id.update_data:
            Uri uri2 = Uri.parse("content://app.nvgtor.com.leanrning.provider/book/" + newId);
            ContentValues values1 = new ContentValues();
            values1.put("name", "A Storm of Swords");
            values1.put("pages", 1216);
            values1.put("price", 24.90);
            getContentResolver().update(uri2, values1, null, null);
            break;
        case R.id.delete_data:
            Uri uri3 = Uri.parse("content://app.nvgtor.com.leanrning.provider/book/" + newId);
            getContentResolver().delete(uri3, null, null);
            break;
    }
}

参考

第一行代码