前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ContentProvider

ContentProvider

作者头像
佛系编码
发布2018-05-22 11:49:09
6490
发布2018-05-22 11:49:09
举报
文章被收录于专栏:Android学习之路

ContentProvider

内容提供者,应用程序间的数据交互,是为存储和获取数据提供的统一接口。 Contentprovider为应用间数据交互提供了安全的环境,它允许把自己的应用数据开放给其他应用进行 CRUD。怎么样进行操作可以自己规定,不用担心权限的问题。

当然如果不想被被人读取自己应用的数据就不需要这个内容提供者。 ContentResolver来访问和操作我们的数据。 ContentResolver 通过我们注册的uri就可以找到我们开放的数据。

关于uri 参考这篇文章:http://blog.csdn.net/dlutbrucezhang/article/details/8917303

创建一个ContentProvider

创建自己的内容提供程序 只需继承ContentProvider即可。 这里就以insert 和 query 为例

代码语言:javascript
复制

package com.skymxc.demo.contentprovider.util;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.support.annotation.Nullable;
import android.text.TextUtils;

/**
 * Created by sky-mxc
 */

public class StudentProvider extends ContentProvider {

    private DBHelper dbHelper;
    private UriMatcher uriMatcher;

    //匹配结果是一张表
    private static final int STUDENTS = 1;
    //匹配结果是一个条数据
    private static final int STUDENT = 2;
    //一般是包名 避免重复
    private static final String AUTHORITY = "com.skymxc.demo";

    @Override
    public boolean onCreate() {
        dbHelper = new DBHelper(getContext());
        //初始化 uri匹配者   UriMatcher.NO_MATCH:匹配不上时返回
        uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

        //添加能够匹配的uri格式 参数1authorities 匹配住机。  参数2 匹配路径   参数3 code : match success  return this code;
        // 代表这个uri 操作的是一个表,匹配码是 STUDENTS
        uriMatcher.addURI(AUTHORITY,"student", STUDENTS);
        //代表这个uri 操作的是一条数据 匹配成功后返回 STUDENT
        uriMatcher.addURI(AUTHORITY,"student/#",STUDENT);
        return true;
    }

    /**
     *  查询操作
     * @param uri
     * @param projection 要查询的列
     * @param condition 查询条件
     * @param values 查询参数
     * @param sortOrder 排序
     * @return
     */
    @Nullable
    @Override
    public Cursor query(Uri uri, String[] projection, String condition, String[] values, String sortOrder) {
        Cursor cursor =null;
        SQLiteDatabase db= dbHelper.getDB();
        //匹配这个uri 要查询一张表还是 某条数据
        switch (uriMatcher.match(uri)){
            case STUDENT:
                //查询某条数据  ContentUris  :工具类 可以解析出id
                long id= ContentUris.parseId(uri);
                String where ="_id ="+id+" ";
                if (!TextUtils.isEmpty(condition)){
                    where+= " and "+condition;
                }
               cursor= db.query(DBHelper.TABLE_NAME,projection,where,values,null,null,sortOrder);
                break;
            case STUDENTS:
                //查询一张表
                cursor = db.query(DBHelper.TABLE_NAME,projection,condition,values,null,null,sortOrder);
                break;
            default:
                throw new IllegalArgumentException("match fail 。uri:"+uri+"");

        }
        return cursor;
    }

    @Nullable
    @Override
    public String getType(Uri uri) {
        String type="unKnow";
        switch (uriMatcher.match(uri)){
            case STUDENT:
                type="vnd.android.cursor.item/student";
                break;
            case STUDENTS:
                type= "vnd.android.cursor.dir/student";
                break;
        }
        return null;
    }

    @Nullable
    @Override
    public Uri insert(Uri uri, ContentValues values) {
        SQLiteDatabase db = dbHelper.getDB();
        switch (uriMatcher.match(uri)){
            case STUDENT:
                break;
            case STUDENTS:
                db.insert(DBHelper.TABLE_NAME,"_id",values);
                break;
        }
        return uri;
    }

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

创建完之后还需要在manifest文件中注册 才能被其他应用看到,通过 元素注册一个内容提供者

代码语言:javascript
复制
<!--
    android:exported 设置此provider是否可以被其他应用使用。
    android:readPermission 该provider的读权限的标识
    android:writePermission 该provider的写权限标识
    android:permission provider读写权限标识
    android:grantUriPermissions 临时权限标识

-->
<provider
    android:authorities="com.skymxc.demo"
    android:name=".util.StudentProvider"
    android:exported="true"/>

关于临时权限标识 grantUriPermissions :true时,意味着该provider下所有数据均可被临时使用;false时,则反之,但可以通过设置标签来指定哪些路径可以被临时使用。这么说可能还是不容易理解,我们举个例子,比如你开发了一个邮箱应用,其中含有附件需要第三方应用打开,但第三方应用又没有向你申请该附件的读权限,但如果你设置了此标签,则可以在start第三方应用时,传入FLAG_GRANT_READ_URI_PERMISSION或FLAG_GRANT_WRITE_URI_PERMISSION来让第三方应用临时具有读写该数据的权限。

到这里 一个简单的内容提供者就创建完成了


ContentResolver

可以看做是客户端 与ContentProvider 对应 ,ContentProvider 负责提供数据操作接口 ,ContentResolver 可以调用ContentProvider的数据接口对数据进行操作

为了测试上面定义的ContentProvider ,另创建一个Module 进行读取

代码语言:javascript
复制
private void read() {
    ContentResolver resolver= getContentResolver() ;
    String uriStr ="content://com.skymxc.demo/student";
   Cursor cursor= resolver.query(Uri.parse(uriStr),new String[]{"_id","name","age"},null,null,"age");
    StringBuffer sb = new StringBuffer("============student==================\n");

        while (cursor !=null &&cursor.moveToNext()){

            long id = cursor.getLong(cursor.getColumnIndex("_id"));
            String name = cursor.getString(cursor.getColumnIndex("name"));
            int age = cursor.getInt(cursor.getColumnIndex("age"));
            sb.append("==="+id+"===\n");
            sb.append("name:"+name+"\n");
            sb.append("age:"+age+"\n");
        }
    sb.append("============================");
        tv.setText(sb.toString());
    if (cursor != null){
        cursor.close();
    }
}

insert

代码语言:javascript
复制

private void insert() {
    String name = etName.getText().toString();
    String  age = etAge .getText().toString();

    ContentResolver resolver = getContentResolver();
    String uriStr="content://com.skymxc.demo/student";
    ContentValues cv = new ContentValues();
    cv.put("name",name);
    cv.put("age",age);
    resolver.insert(Uri.parse(uriStr),cv);
}

ContentResolver 还可以用来操作 短信,联系人,多媒体等 数据,这里写个读取短信的实例

读取短信的权限

代码语言:javascript
复制
><uses-permission android:name="android.permission.READ_SMS"/>
>`
代码语言:javascript
复制
/**
 * 短信查询
 */
private void querySms() {
    String[] projection = new String[]{"_id","address","person","body","type"};
    StringBuffer sb = new StringBuffer("短信数据=============\n");
    ContentResolver resolver= getContentResolver();
    Cursor cursor = resolver.query(Uri.parse("content://sms/"),projection,null,null,null);
    while (cursor != null && cursor.moveToNext()){
        sb.append("id:"+cursor.getInt(cursor.getColumnIndex("_id")));
        sb.append("\naddress:"+cursor.getString(cursor.getColumnIndex("address")));
        sb.append("\nperson:"+cursor.getString(cursor.getColumnIndex("person")));
        sb.append("\nbody:"+cursor.getString(cursor.getColumnIndex("body")));
        sb.append("\ntype:"+cursor.getString(cursor.getColumnIndex("type")));
        sb.append("\n=================================================");
    }

    tv.setText(sb.toString());
}

ContentObserver

内容观察者,可以给某些数据注册观察者,当数据改变时做出有些操作

初始化观察者

代码语言:javascript
复制
private ContentObserver  observer = new ContentObserver(new Handler()) {
   @Override
   public void onChange(boolean selfChange) {
       super.onChange(selfChange);
       Log.e("MainActivity","======数据改变了===");
   }
};
`

注册观察者

代码语言:javascript
复制

Uri uri = Uri.parse("content://"+StudentProvider.AUTHORITY+"/student");
//为student 注册观察者
/**
 * parameter1 观察的uri
 * parameter2 uri的后代是否连带 观察
 * parameter3 observer
 */
getContentResolver().registerContentObserver(uri,true,observer);

内容改变时 通知观察者

系统会首先查找 uri 扫描(手机上)所有的注册的observer 的uri 匹配之后执行 observer的onChange 方法

代码语言:javascript
复制
@Nullable
@Override
public Uri insert(Uri uri, ContentValues values) {
    SQLiteDatabase db = dbHelper.getDB();
    int line=0;
    switch (uriMatcher.match(uri)){
        case STUDENT:
            break;
        case STUDENTS:
          line= (int) db.insert(DBHelper.TABLE_NAME,"_id",values);


            break;
    }
    if (line>0){
        getContext().getContentResolver().notifyChange(uri,null);
    }

    return uri;
}

当在另一个应用插入数据时 change()调用

代码语言:javascript
复制
E/MainActivity: ======数据改变了===
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016-10-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ContentProvider
    • 创建一个ContentProvider
      • ContentResolver
        • ContentObserver
        相关产品与服务
        对象存储
        对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档