注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好。
原文链接: http://developer.android.com/training/secure-file-sharing/request-file.html
当一个希望访问由其它应用所共享的文件时,需求应用(即客户端)经常会向其它应用(服务端)发送一个文件需求。在大多数情况下,这个需求会在服务端应用启动一个 Activity 显示可以共享的文件。当服务应用向客户应用返回了URI后,用户即选择了文件。
这节课向你展示一个客户应用如何向服务应用需求一个文件,接受服务应用发来的URI,然后使用这个URI打开这个文件。
一). 发送一个文件需求
为了向服务应用发送文件需求,在客户应用,需要调用
startActivityForResult
,同时传递给这个方法一个
Intent
,它包含了客户应用能处理的某行为,比如
ACTION_PICK
;以及一个MIME类型。
例如,下面的代码展示了如何向服务端应用发送一个
Intent
,来启动在
Sharing a File
(博客链接:
http://www.cnblogs.com/jdneo/p/3480677.html
)中提到的
Activity
:
public
class
MainActivity
extends
Activity {
private
Intent mRequestFileIntent;
private
ParcelFileDescriptor mInputPFD;
...
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRequestFileIntent
=
new
Intent(Intent.ACTION_PICK);
mRequestFileIntent.setType(
"image/jpg"
);
...
}
...
protected
void
requestFile() {
/**
* When the user requests a file, send an Intent to the
* server app.
* files.
*/
startActivityForResult(mRequestFileIntent,
0
);
...
}
...
}
二). 访问需求的文件
当服务应用向客户应用发回包含URI的 Intent 时,这个 Intent 会传递给客户应用的覆写的 onActivityResult() 方法当中。一旦客户应用有了文件的URI,它就可以通过获取其 FileDescriptor 来访问文件。
文件的安全问题在这一过程中不用过多担心,因为这个客户应用所受到的所有数据只有URI而已。由于URI不包含目录路径,客户应用无法查询出或者打开任何服务应用的其他文件。客户应用仅仅获取了这个文件的访问渠道和访问的权限。同时访问权限是临时的,一旦这个客户应用的任务栈被完成了,这个文件将只能被服务应用访问。
下面的例子展示了客户应用如何处理发自服务应用的
Intent
,以及如何客户应用使用URI获取
FileDescriptor
:
/*
* When the Activity of the app that hosts files sets a result and calls
* finish(), this method is invoked. The returned Intent contains the
* content URI of a selected file. The result code indicates if the
* selection worked or not.
*/
@Override
public
void
onActivityResult(
int
requestCode,
int
resultCode,
Intent returnIntent) {
//
If the selection didn't work
if
(resultCode !=
RESULT_OK) {
//
Exit without doing anything else
return
;
}
else
{
//
Get the file's content URI from the incoming Intent
Uri returnUri =
returnIntent.getData();
/*
* Try to open the file for "read" access using the
* returned URI. If the file isn't found, write to the
* error log and return.
*/
try
{
/*
* Get the content resolver instance for this context, and use it
* to get a ParcelFileDescriptor for the file.
*/
mInputPFD
= getContentResolver().openFileDescriptor(returnUri, "r"
);
}
catch
(FileNotFoundException e) {
e.printStackTrace();
Log.e(
"MainActivity", "File not found."
);
return
;
}
//
Get a regular file descriptor for the file
FileDescriptor fd =
mInputPFD.getFileDescriptor();
...
}
}
方法 openFileDescriptor() 返回一个文件的 ParcelFileDescriptor 。从这个对象中,客户应用可以获取 FileDescriptor 对象,然后用户就可以利用这个对象读取这个文件。

