ContentProvider简单学习

ContentProvider 对应用之间数据访问起着很重要的作用,比如我们在自己的应用中去获取联系人信息,相册图片等

文中主要涉及的知识点

  • UriMatcher
  • SQLiteOpenHelper
  • ContentProvider
  • ContentProvider配置权限等

开始之前,建议将外部访问的Uri参数进行常量化

先来看看Uri格式
这里写图片描述

Authority: 授权信息,用以区别不同的ContentProvider;
Path: 表名,用以区分ContentProvider中不同的数据表;
Id: Id号,用以区别表中的不同数据;

进行常量定义如下:

public class MyContract {

    public static final String CONTENT_AUTHORITY = "com.yeaper.contentproviderdemo";
    public static final Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY);
    public static final String PATH_TEST = "test";

    public static final class TestEntry implements BaseColumns {
        public static final Uri CONTENT_URI = BASE_CONTENT_URI.buildUpon().appendPath(PATH_TEST).build();

        public static Uri buildUri(long id) {
            return ContentUris.withAppendedId(CONTENT_URI, id);
        }

        public static final String TABLE_NAME = "test";
        public static final String COLUMN_NAME = "name";
    }

}

一、UriMatcher

主要用于匹配外部访问时,传进来的 Uri

 final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
 final String authority = MyContract.CONTENT_AUTHORITY;
 matcher.addURI(authority, MyContract.PATH_TEST, code);
  • addURI(authority, MyContract.PATH_TEST, TEST);

    • 这行代码是添加外部访问路径,可添加多个
  • matcher.match(uri)

    • 会将 uri 和 addUri 方法添加的 uri 进行匹配,返回对应 code,再进行数据操作

二、SQLiteOpenHelper

自定义数据库助手类,完成数据库相关操作

public class MyDBOpenHelper extends SQLiteOpenHelper {

    /**
     *
     * @param context 上下文
     * @param db_name 数据库名
     * @param db_version 数据库版本
     */
    public MyDBOpenHelper(Context context, String db_name, int db_version) {
        super(context, db_name, null, db_version);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        // 创建表的语句
        final String SQL_CREATE_CONTACT_TABLE = "CREATE TABLE " + MyContract.TestEntry.TABLE_NAME + "( "
                + MyContract.TestEntry._ID + " TEXT PRIMARY KEY, "
                + MyContract.TestEntry.COLUMN_NAME + " TEXT NOT NULL );";

        db.execSQL(SQL_CREATE_CONTACT_TABLE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + MyContract.TestEntry.TABLE_NAME);
        onCreate(db);
    }
}

三、ContentProvider

  • 自定义 ContentProvider,实现它的六个方法,其中 insert、delete、query、update 对应数据库的增删查改
  • 外部 APP 使用 ContentResolver 时会传进 Uri,进行四大操作之前先通过UriMatcher进行匹配,通过即可进行操作
public class MyContentProvider extends ContentProvider {

    private MyDBOpenHelper mOpenHelper;

    @Override
    public boolean onCreate() {
        mOpenHelper = new MyDBOpenHelper(getContext(), "contact.db", 1001);
        return true;
    }

    @Nullable
    @Override
    public String getType(Uri uri) {
        return null;
    }

    @Nullable
    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        final SQLiteDatabase db = mOpenHelper.getReadableDatabase();

        Cursor cursor = null;
        switch ( buildUriMatcher().match(uri)) {
            case TEST:
                cursor = db.query(MyContract.TestEntry.TABLE_NAME, projection, selection, selectionArgs, sortOrder, null, null);
                break;
        }

        return cursor;
    }

    @Nullable
    @Override
    public Uri insert(Uri uri, ContentValues values) {
        final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
        Uri returnUri;
        long _id;
        switch ( buildUriMatcher().match(uri)) {
            case TEST:
                _id = db.insert(MyContract.TestEntry.TABLE_NAME, null, values);
                if ( _id > 0 )
                    returnUri = MyContract.TestEntry.buildUri(_id);
                else
                    throw new android.database.SQLException("Failed to insert row into " + uri);
                break;
            default:
                throw new android.database.SQLException("Unknown uri: " + uri);
        }
        return returnUri;
    }

    @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;
    }

    private final static int TEST = 100;

    static UriMatcher buildUriMatcher() {
        final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
        final String authority = MyContract.CONTENT_AUTHORITY;

        matcher.addURI(authority, MyContract.PATH_TEST, TEST);

        return matcher;
    }
}

四、ContentProvider配置权限等

  • 注册ContentProvider
<provider
    android:authorities="com.yeaper.contentproviderdemo"
    android:name=".provider.MyContentProvider"/>

想让外部 APP 能访问到,需要给 provider 配置属性

android:readPermission="com.yeaper.contentproviderdemo.READ"
android:writePermission="com.yeaper.contentproviderdemo.WRITE"
android:exported="true"

并申明读写权限

<permission android:name="com.yeaper.contentproviderdemo.READ" android:protectionLevel="normal"/>
<permission android:name="com.yeaper.contentproviderdemo.WRITE" android:protectionLevel="normal"/>

其中,android:exported 属性让provider可以被外界访问,权限可以控制外部对本应用内数据的操作权限,还有其他属性就不介绍了


最后,外部使用如下:

先添加读写权限,注意,这里是 uses-permission 标签

<uses-permission android:name="com.yeaper.contentproviderdemo.READ" />
<uses-permission android:name="com.yeaper.contentproviderdemo.WRITE"/>

然后使用 ContentResolver 传进 Uri 进行数据操作,此处的 Uri 就是前面定义的常量

Uri uri = Uri.parse("content://com.yeaper.contentproviderdemo/test");
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
if(cursor == null) return;

try {
    other_data.setText("total data number = " + cursor.getCount());
} finally {
    cursor.close();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值