android ContentProvider实现跨进程文件传输

1.前序:
提到ContentProvider ,我们首先想到的是“增删查改”,数据库访问,有点雷雨jdbc 其实还提供的一个服务,共享文件。
2.使用场景:
1.进程之间共享文件数据
2.由于权限问题,需要将数据迁移到低权限区域问题(我们知道Android自L开始,权限越加严格,很多文件不发轻易被外部访问)

3.实例

问题:A B 两个进程,且由于权限不可互访. B进程需要访问A进程数据怎么办呢?
这里采用方案:将文件复制到B权限目录去是可行的

code:
1).A进程,如何复制到B
Uri  uriA, uriB
Uri uirBProvider= Uri.parse("content://" + AUTHORITY + "/"
            +TABLE);
Uri uriB = mContentResolver.insert(uirBProvider, mContentValues); (1)//这里(1),(2),(3),(4)标注为按顺序来

inputStream = mContentResolver.openInputStream(uriA);  (2)
outputStream = mContentResolver.openOutputStream(uriB);
byte[] data = new byte[3 * 1024];
int num;
while ((num = inputStream.read(data)) > 0) {
    outputStream.write(data, 0, num);
}

2).B进程,复制到B的哪里去了呢?B进程的provider是BProvider

OurSQLiteOpenHelper  mDbHelper
ContentValues        values
BContentProvider{

    @Override
    public Uri insert(Uri uri, ContentValues values) {
         //这里为何要插入呢?这里表中有这两个字段:一个真是绝对路径,一个存uri(方便查询真实路径)。这里先创建好目准备存储文件,同事存储好//uri+rowId
        //方便(2)处的的使用,(2)处最终调用(3)才使用到这里的存储值
        values = values.put("_data", createDataFile()); (4)
        rowId = mDbHelper.getWritableDatabase().insert(TABLE, "", values);
        Uri rowUri = ContentUris.appendId(uri.buildUpon(), rowId).build();
        return  rowUri;
    }

  //这里很重要,复制文件需要重写这个方法,(2)处openOutputStream,打开的就是这里查到的文件,也是insert生成的文件
    @Override
    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
        log("openFile: " + uri + "path:" + uri.getPath());
        return openFileHelper(uri, mode); (3)
    }

}
3).B进程中,(3)处代码的意义?
其实是ContentProvider自带的,当然我们可以重写(这里未粘贴全),其实就是获取(4)处createDataFile生成的文件地址

protected final @NonNull ParcelFileDescriptor openFileHelper(@NonNull Uri uri,
        @NonNull String mode) throws FileNotFoundException {
   //"_data" 字段即是(4)处存入的地址
    Cursor c = query(uri, new String[]{"_data"}, null, null, null);
    int count = (c != null) ? c.getCount() : 0;
    ........
    c.moveToFirst();
    int i = c.getColumnIndex("_data");
    String path = (i >= 0 ? c.getString(i) : null);
    c.close();
    return ParcelFileDescriptor.open(new File(path), modeBits);
}

你可能感兴趣的:(android)