Android五大组件-ContentProvider

使用场景

ContentProvider可以在应用间共享数据,或者说ContentProvider可以把本应用的数据暴露给其他应用,提供有限的(应用自身可控制的)增删改查

使用方法

应用A,把数据暴露出去(为使代码简单明了,代码里删去具体数据库操作部分)

public class MyContentProvider extends ContentProvider{

    private static final String AUTHORITY = "com.android.mycontentprovider";

    private static final int ITEMS = 1;
    private static final int ITEM_ID = 2;
    private static final int ITEM = 3;

    private ContentResolver resolver = null;
    @Override
    public boolean onCreate() {
        resolver = getContext().getContentResolver();
        return false;
    }
    private static final UriMatcher uriMatcher;
    static {
        uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        uriMatcher.addURI(AUTHORITY, "item", ITEMS);//匹配所有item,例如查询则是查询所有item
        uriMatcher.addURI(AUTHORITY, "item/#", ITEM_ID);//匹配单个item,id为xxx的item,例如删除则是删除id为xxx的item
        uriMatcher.addURI(AUTHORITY, "item/#", ITEM);//匹配单个item,例如插入一个item
    }
    /**
     * 返回对应的内容类型
     * 如果返回集合的内容类型,必须以vnd.android.cursor.dir开头
     * 如果是单个元素,必须以vnd.android.cursor.item开头
     */
    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        switch(uriMatcher.match(uri)){
            case ITEM_ID:
                return "vnd.android.cursor.item/person";
            case ITEMS:
                return "vnd.android.cursor.dir/person";
            default:
                throw new IllegalArgumentException("this is unkown uri:" + uri);
        }
    }
    /*
    * 根据匹配值做查询并返回结果集
    * */
    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
        switch (uriMatcher.match(uri)){
            case ITEM_ID://查询id为xxx的ITEM
                String id = uri.getPathSegments().get(1);//查询第一个参数即id
                break;
            case ITEMS://查询所有item
                break;
        }
        SQLiteQueryBuilder sqlBuilder = new SQLiteQueryBuilder();
        Cursor cursor = sqlBuilder.query(null,null,null,null,null,null,null);//假设这里做了相对的查询
        cursor.setNotificationUri(resolver,uri);
        return cursor;
    }
    /*
    * 根据匹配值做删除数据库操作并按要求返回Uri
    * */
    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
        Uri insertUri = null;
        switch(uriMatcher.match(uri)){
            case ITEM:
                //做插入数据values里有每个字段的值
                int id = 0;//假设这个id为插入后返回的id值
                insertUri = ContentUris.withAppendedId(uri, id);
                break;
        }
        return insertUri;
    }
    /*
    * 根据匹配值做删除操作并返回是否删除成功
    * */
    @Override
    public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
        return 0;
    }
    /*
    * 根据匹配值做更新操作并返回是否更新成功
    * */
    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
        return 0;
    }
}

在AndroidManifest.xml里注册,android:authorities是其他应用能找到我们这个ContentProvider的凭据

<provider android:name=".MyContentProvider"          android:authorities="com.android.mycontentprovider"  />  

应用B,访问应用A的数据

        ContentResolver mContentResolver = context.getContentResolver();
        //content: 这部分是android定义的。ContentProvider专属,表示数据由ContentProvider提供
        //com.android.mycontentprovider这就是我们的凭证了,要跟AndroidManifest.xml里配置的对上号
        //item这部分就是匹配用的了
        Uri uri = Uri.parse("content://com.android.mycontentprovider/item");
        ContentValues values = new ContentValues();
        values.put("name","huangshunbo");
        values.put("age",19);
        mContentResolver.insert(uri,values);//插入一条数据name=huangshunbo,age=19
        uri = Uri.parse("content://com.android.mycontentprovider/item/1");
        mContentResolver.delete(uri,"name = ?",new String[]{"huangshunbo"});//将id=1,name=huangshunbo的记录的删除
        mContentResolver.update(uri,values,null,null);//更新数据
        mContentResolver.query(uri,new String[]{"name"},null,null,null);//查询id为1的数据并只返回name字段

权限与数据监听

ContentProvider是可以进行权限设置的,就是说如果应用A设置了权限,那么应用B想要获取应用A的数据或者修改A的数据需要在AndroidManifest.xml中进行权限申请。具体如下
应用A可以设置android:permission/android:readPermission/android:writePermission三个权限。第一个的优先级最低,如没有设置第二第三个权限则拥有第一个权限即可操作读写。另外android:exported是否暴露自身,true则第三方应用可以访问到,false则只有自身或用户id一样的应用方可访问到

<provider  
    provider android:name=".MyContentProvider"
    android:authorities="com.android.mycontentprovider"  
    android:exported="true"  
    android:permission="com.android.mycontentprovider"  
    android:readPermission="com.android.mycontentprovider.read"  
    android:writePermission="com.android.mycontentprovider.write"/>  

然后com.android.mycontentprovider等的字符串目前是没有意义的,需在application标签的同级目录,写上申请permission的代码

<permission  
    android:name="com.android.mycontentprovider"  
    android:label="provider pomission"  
    android:protectionLevel="normal" />  

这样应用A的权限控制就设置好了,应用B想访问的话就必须申请权限了

<uses-permission android:name="com.android.mycontentprovider"/>  

数据监听 这个就简单了,就是个观察者模式,首先需要在应用A这边新建一个类继承ContentObserver,数据变化会通知到这里。然后注册

getContentResolver().registerContentObserver(CONTENT_URI_FIRST,true,observer);

不用的时候记得注销

getContentResolver().unregisterContentObserver(observer);  

最后每当应用B这边数据变动时调用如下通知众观察者

getContext().getContentResolver().notifyChange(uri, null);  

源码

待续。。。

  • 说说 ContentProvider、ContentResolver、ContentObserver 之间的关系
    a. ContentProvider 内容提供者,用于对外提供数据
    b. ContentResolver 用于获取ContentProvider提供的数据,注册ContentObserver监听,提醒数据变化
    c. ContentObserver 监听器,可以监听数据的改变
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值