Training—Sharing Files
阅读:http://developer.android.com/training/secure-file-sharing/index.html
首先要先注册一个FileProvider。
<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>
authorities必须是自己程序的包名+fileprovider,resource对应的是下面即将提到的路径问题。
<paths> <files-path path="images/" name="myimages" /> </paths>
In this example, the
<files-path>
tag shares directories within thefiles/
directory of your app's internal storage.
其实就是定义了internal storage里的files的images文件,最后的URI形式是:content://com.example.myapp.fileprovider/myimages/default_image.jpg。
要分享,就是为他人提供文件地址嘛,因此要使用带有ACTION_PICK
的过滤器:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> ... <application> ... <activity android:name=".FileSelectActivity" android:label="@"File Selector" > <intent-filter> <action android:name="android.intent.action.PICK"/> <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.OPENABLE"/> <data android:mimeType="text/plain"/> <data android:mimeType="image/*"/> </intent-filter> </activity>
接下来官方说了一大堆,代码我就不贴了,直接说重点。
既然对方Activity是使用startActivityForResult() 的,因此我们必须返回相关的数据给它。
找到File的地址然后生成File对象,然后使用:
fileUri = FileProvider.getUriForFile( MainActivity.this, "com.example.myapp.fileprovider", requestFile);
获得URI,当然还要有权限:
mResultIntent.addFlags(
Intent.FLAG_GRANT_READ_URI_PERMISSION);
接下来设置一下就行了:
mResultIntent.setDataAndType( fileUri, getContentResolver().getType(fileUri)); // Set the result MainActivity.this.setResult(Activity.RESULT_OK, mResultIntent);
一般处理完之后,这个Activity就不用了,直接finish就行了。
同样,有发就有得收。
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); ... } ... }
/* * 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(); ... } }
其实这个过程似乎有些麻烦,不过这是因为,我们能读取该文件的权限是临时的,一旦当前程序栈结束,就再没有权限访问了。
通过URI还能获取文件信息,不再累述,这里看:http://developer.android.com/training/secure-file-sharing/retrieve-info.html