Android开发Android开发

1-4 ContentProvider基础全纪录

2019-12-16  本文已影响0人  Shimmer_

[TOC]


ContentProvider.png

1. 定义

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() 初始化内容提供器<br />通常在这里完成数据库的创建、升级等操作 返回值表示创建成功与否<br />它的执行早于Application的OnCreate;
String getType(Uri uri) 根据传入的内容URI来返回相应的MIME类型 必须实现<br />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未做权限适配,需要手动给予通讯录权限
上一篇 下一篇

猜你喜欢

热点阅读