Android ContentProvider进程内通信

本章节讲述使用ContentProvider实现进程内通信 数据来源是SQLite


1.AndroidManifest.xml配置文件

<provider
       android:name=".provider.MyContentProvider"
       android:authorities="com.wjn.mycontentprovider"
       android:enabled="true"
       android:exported="true">

 </provider>


android:exported属性设置成true:可被其他应用使用;
android:exported属性设置成false:只能被自己所在的应用使用;


2.ContentProvider实现类

public class MyContentProvider extends ContentProvider {

    private Context mContext;
    private DBSQLiteOpenHelper mDbHelper = null;
    private SQLiteDatabase db = null;
    public static final String AUTOHORITY = "com.wjn.mycontentprovider";//设置ContentProvider的唯     一标识 AndroidManifest.xml配置


    public static final int User_Code = 1;
    public static final int Job_Code = 2;


    // UriMatcher类使用:在ContentProvider 中注册URI
    private static final UriMatcher mMatcher;
    static{
        mMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        // 初始化
        // 若URI资源路径 = content://cn.scu.myprovider/user ,则返回***User_Code
        mMatcher.addURI(AUTOHORITY,"mytable", User_Code);
        // 若URI资源路径 = content://cn.scu.myprovider/job ,则返回***Job_Code
        mMatcher.addURI(AUTOHORITY, "mytable", Job_Code);
    }


    /**
     * delete方法 删除数据
     * */


    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        // 根据URI匹配 URI_CODE,从而匹配ContentProvider中相应的表名
        String table = getTableName(uri);
        return db.delete(table,selection,selectionArgs);
    }


    /**
     * getType方法 获取数据类型
     * */


    @Override
    public String getType(Uri uri) {
        // 由于不展示,此处不作展开
        return null;
    }


    /**
     * insert方法 插入数据
     * */


    @Override
    public Uri insert(Uri uri, ContentValues values) {
        // 根据URI匹配 URI_CODE,从而匹配ContentProvider中相应的表名
        String table = getTableName(uri);
        // 向该表添加数据
        db.insert(table, null, values);
        // 当该URI的ContentProvider数据发生变化时,通知外界(即访问该ContentProvider数据的访问者)
        mContext.getContentResolver().notifyChange(uri, null);
        return uri;
    }


    /**
     * onCreate方法
     * 在ContentProvider创建时对数据库进行初始化
     * 运行在主线程
     * */


    @Override
    public boolean onCreate() {
        mContext = getContext();
        mDbHelper = new DBSQLiteOpenHelper(getContext(),"cdsp.db",null,1);
        db = mDbHelper.getWritableDatabase();
        db.execSQL("delete from mytable");//删除表中所有信息 可以做别的操作
        return true;
    }


    /**
     * query方法 查询数据
     * */


    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        // 根据URI匹配 URI_CODE,从而匹配ContentProvider中相应的表名
        String table = getTableName(uri);
        // 查询数据
        return db.query(table,projection,selection,selectionArgs,null,null,sortOrder,null);
    }


    /**
     * update方法 更新数据
     * */


    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        // 根据URI匹配 URI_CODE,从而匹配ContentProvider中相应的表名
        String table = getTableName(uri);
        return db.update(table,values,selection,selectionArgs);
    }


    /**
     * 根据URI匹配 URI_CODE,从而匹配ContentProvider中相应的表名
     */
    private String getTableName(Uri uri){
        String tableName = null;
        switch (mMatcher.match(uri)) {
            case User_Code:
                tableName = "mytable";
                break;
            case Job_Code:
                tableName = "mytable";
                break;
        }
        return tableName;
    }


}


3.SQLiteOpenHelper实现类


public class DBSQLiteOpenHelper extends SQLiteOpenHelper{


    /**
     * 构造方法
     * */


    public DBSQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }


    /**
     * onCreate方法
     * 首次使用软件时生成数据库表
     * */


    @Override
    public void onCreate(SQLiteDatabase db) {
        String sql="CREATE TABLE mytable( id INTEGER, name VARCHAR(10), describe TEXT)";
        db.execSQL(sql);
    }


    /**
     * onUpgrade方法
     * 在数据库的版本发生变化时会被调用, 一般在软件升级时才需改变版本号
     * */


    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        String sql="DROP TABLE IF EXISTS mytable";
        db.execSQL(sql);
        onCreate(db);
    }


}



4.java代码调用

private  Uri uri_user;

// 设置URI

uri_user = Uri.parse("content://com.wjn.mycontentprovider/mytable");


// 插入表中数据

ContentValues values = new ContentValues();

values.put("id", 1);

values.put("name", "詹姆斯");

values.put("describe", "大家好,我是詹姆斯!");

// 获取ContentResolver

ContentResolver resolver =  getContentResolver();

// 通过ContentResolver 根据URI 向ContentProvider中插入数据

resolver.insert(uri_user,values);



// 获取ContentResolver
ContentResolver resolver =  getContentResolver();

resolver.delete(uri_user,"id=1",null);


// 获取ContentResolver
 ContentResolver resolver =  getContentResolver();
 ContentValues values=new ContentValues();//类似于map
 values.put("name","API修改");
 values.put("describe","大家好,我修改成功了!");

 resolver.update(uri_user,values,"id=1",null);


// 获取ContentResolver
ContentResolver resolver =  getContentResolver();
// 通过ContentResolver 向ContentProvider中查询数据
Cursor cursor = resolver.query(uri_user, new String[]{"id","name","describe"}, null, null, null);
StringBuilder sbBuilder=new StringBuilder();
while (cursor.moveToNext()){
         int id=cursor.getInt(cursor.getColumnIndex("id"));
         sbBuilder.append("ID:"+id+"\n");
         String name=cursor.getString(cursor.getColumnIndex("name"));
         sbBuilder.append("姓名:"+name+"\n");
         String describe=cursor.getString(cursor.getColumnIndex("describe"));
         sbBuilder.append("描述:"+describe+"\n\n\n");
}
textView6.setText(sbBuilder.toString());
cursor.close();// 关闭游标


5.结果

5.1.“增”——>“查”

Android ContentProvider进程内通信


5.2.“改”——>“查”

Android ContentProvider进程内通信


5.3.“删”——>"查"

Android ContentProvider进程内通信



6.ContentProvider优点

6.1.安全

ContentProvider为应用间的数据交互提供了一个安全的环境:允许把自己的应用数据根据需求开放给 其他应用 进行 增、删、改、查,而不用担心因为直接开放数据库权限而带来的安全问题。


6.2.访问简单高效

对比于其他对外共享数据的方式,数据访问方式会因数据存储的方式而不同:

6.2.1.采用 文件方式 对外共享数据,需要进行文件操作读写数据。


6.2.2.采用 Sharedpreferences 共享数据,需要使用sharedpreferences API读写数据


6.2.3.而采用ContentProvider方式,其 解耦了 底层数据的存储方式,使得无论底层数据存储采用何种方式,外界对数据的访问方式都是统一的,这使得访问简单 & 高效 。

Android ContentProvider进程内通信



7.总结

Android ContentProvider进程内通信