ContentProvider基础全纪录


ContentProvider

1. 定义

  • Android四大组件之一
  • 用于在不同应用程序之间实现数据共享的功能
  • 内容提供其可以选择只对哪一部分数据进行共享,保证隐私数据的安全性

2. 使用

1. 使用 ContentResolver访问其他应用中数据

ContentResolver的方法说明补充
Cursor query(Uri uri,String[] projection, String selection,String[] selectionArgs, String sortOrder)查询uri:内容URI,给数据建立唯一标识符
projection:指定查询的列名
selection:指定的约束条件
selectionArgs:约束条件中具体的值
sortOrder:排序方式
Uri insert(Uri url, ContentValues values)新增uri:内容URI,给数据建立唯一标识符
values:插入数据的数据集
int update(Uri uri, ContentValues values, String where, String[] selectionArgs)修改uri:内容URI,给数据建立唯一标识符
values:要修改数据的数据集
where:指定的约束条件
selectionArgs:约束条件中具体的值
int delete(Uri url, @Nullable String where, String[] selectionArgs)删除uri:内容URI,给数据建立唯一标识符
where:指定的约束条件
selectionArgs:约束条件中具体的值

Uri: 主要有两部分组成,authority和path

  • authority用于对不同的应用程序做区分,一般为了避免冲突,都会采用程序包名的方式进行命名
  • path用于对同一应用程序不同表做区分,通常添加到authority后面

标准格式写法
content://com.xxx.app.provider/table
表示调用方期望的是访问这个应用程序的table表的数据

content://com.xxx.app.provider/table/1
表示调用方期望的是访问这个应用程序的table表中id为1的数据

路径结尾表示期望访问该表中所有数据

id结尾表示期望访问该表中对应id的数据

读取系统联系人

Cursor cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
if (cursor != 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));
	msgTv.setText(msgTv.getText().toString() + "\n" + "readContacts: " + name + ":" + number);
	}
}

通过Context的getContentResolver方法获取该实例
通过insert()update() delete() query()实现CRUD

2. 创建ContentProvider提供给其他应用程序访问本应用数据

2.1 实现说明

创建MyContentProvider继承ContentProvider,重写6个方法

需实现的方法说明补充
boolean onCreate()初始化内容提供器
通常在这里完成数据库的创建、升级等操作
返回值表示创建成功与否
它的执行早于Application的OnCreate;
String getType(Uri uri)根据传入的内容URI来返回相应的MIME类型必须实现
IMEI含义:简单来说 描述了由uri参数计算出的数据类型
Uri insert(Uri uri, ContentValues values)增,返回一个用于表示这条新纪录的URI参数,同ContentResolver中参数意义
int delete(Uri uri, String selection, String[] selectionArgs)删,返回值为被删除的行数参数,同ContentResolver中参数意义
int update(Uri uri, ContentValues values, String selection,String[] selectionArgs)改,返回值为被更改的行参数,同ContentResolver中参数意义
Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)查,返回值为存储查询结果的cursor参数,同ContentResolver中参数意义

MIME 主要由三部分组成

  • 必须以 vnd 开头

  • content uri 以路径结尾,则后接 android.cursor.dir/
    content uri 以id结尾,则后接 android.cursor.item/

  • 最后接上 vnd.authority(实际值).path(实际值)

    content://com.xxx.app.provider/table
    对应MIME
    vnd.android.cursor.dir/com.xxx.app.provider.table

    content://com.xxx.app.provider/table/1
    对应MIME
    vnd.android.cursor.item/com.xxx.app.provider.table

2.2 自定义ContentProvider

创建参考 a_4_contentprovider_b

package com.sj.a_4_contentprovider_b;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.net.Uri;

import com.sj.a_4_contentprovider_b.db.DBTables;
import com.sj.a_4_contentprovider_b.db.DBUtils;

import java.text.SimpleDateFormat;
import java.util.Date;

public class MyContentProvider extends ContentProvider {

    public static final int DATA_DIR = 0;
    public static final int DATA_ITEM = 1;

    private static UriMatcher uriMatcher;
    private static String AUTHORITY = "com.sj.a_4_contentprovider_b.provider";

    private static String PATH = "data";

    static {
        uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        uriMatcher.addURI(AUTHORITY, PATH, DATA_DIR);
        uriMatcher.addURI(AUTHORITY, PATH + "/#", DATA_ITEM);
    }


    @Override
    public boolean onCreate() {
        ContentValues contentValues = new ContentValues();
        contentValues.put("d1", "D1" + System.currentTimeMillis() + "");
        contentValues.put("d2", "D1" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        DBUtils.insert(DBTables.DATA, null, contentValues);
        contentValues.clear();
        contentValues.put("d1", "D2" + System.currentTimeMillis() + "");
        contentValues.put("d2", "D2" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        DBUtils.insert(DBTables.DATA, null, contentValues);
        contentValues.clear();
        contentValues.put("d1", "D3" + System.currentTimeMillis() + "");
        contentValues.put("d2", "D3" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        DBUtils.insert(DBTables.DATA, null, contentValues);
        contentValues.clear();
        contentValues.put("d1", "D4" + System.currentTimeMillis() + "");
        contentValues.put("d2", "D4" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        DBUtils.insert(DBTables.DATA, null, contentValues);
        return true;
    }

    @Override
    public String getType(Uri uri) {
        switch (uriMatcher.match(uri)) {
            case DATA_DIR:
                return "vnd.android.cursor.dir/" + AUTHORITY + "." + PATH;
            case DATA_ITEM:
                return "vnd.android.cursor.item/" + AUTHORITY + "." + PATH;
            default:
                break;
        }
        return null;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        long id = DBUtils.insert(DBTables.DATA, null, values);
        return Uri.parse("content://" + AUTHORITY + "/" + PATH + "/" + id);
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        switch (uriMatcher.match(uri)) {
            case DATA_DIR:
                return DBUtils.delete(PATH, selection, selectionArgs);
            case DATA_ITEM:
                String dataId = uri.getPathSegments().get(1);
                return DBUtils.delete(PATH, "id=?", new String[]{dataId});
        }
        return 0;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection,
                      String[] selectionArgs) {
        switch (uriMatcher.match(uri)) {
            case DATA_DIR:
                return DBUtils.update(PATH, values, selection, selectionArgs);
            case DATA_ITEM:
                String dataId = uri.getPathSegments().get(1);
                return DBUtils.update(PATH, values, "id=?", new String[]{dataId});
        }
        return 0;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
                        String[] selectionArgs, String sortOrder) {
        switch (uriMatcher.match(uri)) {
            case DATA_DIR:
                return DBUtils.query(PATH, projection, selection, selectionArgs, null, null, sortOrder);
            case DATA_ITEM:
                String dataId = uri.getPathSegments().get(1);
                return DBUtils.query(PATH, projection, "id=?", new String[]{dataId}, null, null, sortOrder);
        }
        return null;
    }
}
2.3 使用

注意uri要完全正确匹配,调用参考 a_4_contentprovider_a

3. 问题

  1. 只有当存在ContentResolver尝试访问本程序中的数据时,才会被初始化 与实际编写时onCreate的触发时机有出入,存在问题待解决
  2. Failed to find provider info for com.sj.a_4_contentprovider_b.provider
    注意清单文件中authorities要写全,不要遗漏 .provider
  3. 示意demo未做权限适配,需要手动给予通讯录权限
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值