Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

ContentProvider简单使用 -- Android学习之路

$
0
0

ContentProvider

sky-mxc 总结 转载注明:https://sky-mxc.github.io


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

当然如果不想被被人读取自己应用的数据就不需要这个内容提供者。

ContentResolver来访问和操作我们的数据。
ContentResolver 通过我们注册的uri就可以知道我们开放的数据。

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

创建一个ContentProvider

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


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文件中注册 才能被其他应用看到,通过 元素注册一个内容提供者

<!--
    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 进行读取

    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


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 还可以用来操作 短信,联系人,多媒体等 数据,这里写个读取短信的实例

读取短信的权限
“`xml

““

/**
 * 短信查询
 */
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

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

初始化观察者

private ContentObserver  observer = new ContentObserver(new Handler()) {
   @Override
   public void onChange(boolean selfChange) {
       super.onChange(selfChange);
       Log.e("MainActivity","======数据改变了===");
   }
};
````

> 注册观察者




<div class="se-preview-section-delimiter"></div>

```java

    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 方法

@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()调用

E/MainActivity: ======数据改变了===

作者:MXiaoChao 发表于2016/10/3 22:28:34 原文链接
阅读:93 评论:0 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>