例如app1请求app2的文件,
1,app1发intent启动app2的一个activity显示文件列表
2,user选择一个文件
3,app2的activity返回文件的uri给app1
(本节主要面向app2怎么实现,也就是提供服务的server端)
关键点:
app1发送intent部分:
这部分非常简单,发送ACTION_PICK即可,最好带上type,例如setType("image/*");
app2提供文件的uri:
app2要返回文件的uri,可以通过FileProvider帮忙实现,在manifest中添加
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapp"> <application ...> <provider android:name="android.support.v4.content.FileProvider" android:authorities="com.example.myapp.fileprovider" android:grantUriPermissions="true" android:exported="false"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/filepaths" /> </provider> ... </application> </manifest>android:authorities提供了这个provider的authority,下面的meta-data是说明为那些文件提供uri,文件名字写在res/xml/filepaths.xml中,这个文件的内容如下:
<paths> <files-path path="images/" name="myimages" /> </paths><paths>可以包含多个子元素,用于定义文件的path和名字。
<files-path>是指app的内部存储中的data/data/package_name/files目录下面,
例如上面这个文件指的是data/data/package_name/files/images这个子目录对应的content uri的path是myimages,
那么这个子目录下面的文件对应的content uri就是content://com.example.myapp.fileprovider/myimages/文件名
还可以有<external-path><cache-path>等子元素定义external storage中和cache目录下的文件。
app2显示file list:
activity生命在manifest中,利用文件系统API把对应文件夹下的文件名字显示在list view中
File mPrivateRootDir = getFilesDir();
// Get the files/images subdirectory;
File mImagesDir = new File(mPrivateRootDir, "images");
// Get the files in the images subdirectory
File[] mImageFiles = mImagesDir.listFiles();
实现onItemClick,在用户点击某一项后返回uri给app1
File requestFile = new File( mImageFilename [ position ] );
//使用 FileProvider 得到 URI
try {
fileUri = FileProvider.getUriForFile( MainActivity.this, "com.example.myapp.fileprovider", requestFile);
} catch (IllegalArgumentException e) {
}
mResultIntent.addFlags( Intent.FLAG_GRANT_READ_URI_PERMISSION); //设置权限
mResultIntent.setDataAndType( fileUri, getContentResolver().getType(fileUri)); //设置data和type返回app1
MainActivity.this.setResult(Activity.RESULT_OK, mResultIntent);
app1可以打开文件:
Uri returnUri = returnIntent.getData(); //获得uri
try {
mInputPFD = getContentResolver().openFileDescriptor(returnUri, "r");
} catch (FileNotFoundException e) {
}
// Get a regular file descriptor for the file
FileDescriptor fd = mInputPFD.getFileDescriptor();
openFileDescriptor返回一个ParcelFileDescriptor,然后他的getFileDescriptor返回FileDescriptor,
可以用FileDescriptor来创建FileInputStream和FileOutputStream。
app1通过uri拿到文件信息:
Uri returnUri = returnIntent.getData();
String mimeType = getContentResolver().getType(returnUri);//拿到type
//FileProvider有默认实现提供name和file size,查询时设置null就可以
Uri returnUri = returnIntent.getData();
Cursor returnCursor = getContentResolver().query(returnUri, null, null, null, null);
int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);