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);
}
提到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);
}