FileProvider android 7 文件共享

翻译成人话比较难,还是尝试阅读原版吧!


FileProvider is a special subclass of ContentProvider that facilitates secure sharing of files associated with an app by creating a content:// Uri for a file instead of a file:/// Uri.

A content URI allows you to grant read and write access using temporary access permissions. When you create an Intent containing a content URI, in order to send the content URI to a client app, you can also call Intent.setFlags() to add permissions. These permissions are available to the client app for as long as the stack for a receiving Activity is active. For an Intent going to a Service, the permissions are available as long as the Service is running.

In comparison, to control access to a file:/// Uri you have to modify the file system permissions of the underlying file. The permissions you provide become available to any app, and remain in effect until you change them. This level of access is fundamentally insecure.

The increased level of file access security offered by a content URI makes FileProvider a key part of Android's security infrastructure.


Defining a FileProvider

Since the default functionality of FileProvider includes content URI generation for files, you don't need to define a subclass in code. Instead, you can include a FileProvider in your app by specifying it entirely in XML. To specify the FileProvider component itself, add a <provider> element to your app manifest. Set the android:name attribute to android.support.v4.content.FileProvider. Set the android:authorities attribute to a URI authority based on a domain you control; for example, if you control the domain mydomain.com you should use the authority com.mydomain.fileprovider. Set theandroid:exported attribute to false; the FileProvider does not need to be public. Set the android:grantUriPermissions attribute to true, to allow you to grant temporary access to files. For example:

<manifest>
    ...
    <application>
        ...
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.mydomain.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            ...
        </provider>
        ...
    </application>
</manifest>

If you want to override any of the default behavior of FileProvider methods, extend the FileProvider class and use the fully-qualified class name in theandroid:name attribute of the <provider> element.

Specifying Available Files

A FileProvider can only generate a content URI for files in directories that you specify beforehand. To specify a directory, specify the its storage area and path in XML, using child elements of the  <paths>  element. For example, the following  paths  element tells FileProvider that you intend to request content URIs for the  images/  subdirectory of your private file area.
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <files-path name="my_images" path="images/"/>
    ...
</paths>

Put the <paths> element and its children in an XML file in your project. For example, you can add them to a new file called res/xml/file_paths.xml. To link this file to the FileProvider, add a <meta-data> element as a child of the <provider> element that defines the FileProvider. Set the <meta-data>element's "android:name" attribute to android.support.FILE_PROVIDER_PATHS. Set the element's "android:resource" attribute to @xml/file_paths(notice that you don't specify the .xml extension). For example:

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="com.mydomain.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>

Generating the Content URI for a File

To share a file with another app using a content URI, your app has to generate the content URI. To generate the content URI, create a new File for the file, then pass the File to getUriForFile(). You can send the content URI returned by getUriForFile() to another app in an Intent. The client app that receives the content URI can open the file and access its contents by calling ContentResolver.openFileDescriptor to get a ParcelFileDescriptor.

For example, suppose your app is offering files to other apps with a FileProvider that has the authority com.mydomain.fileprovider. To get a content URI for the file default_image.jpg in the images/ subdirectory of your internal storage add the following code:

File imagePath = new File(Context.getFilesDir(), "images");
File newFile = new File(imagePath, "default_image.jpg");
Uri contentUri = getUriForFile(getContext(), "com.mydomain.fileprovider", newFile);
As a result of the previous snippet,  getUriForFile()  returns the content URI  content://com.mydomain.fileprovider/my_images/default_image.jpg .

Granting Temporary Permissions to a URI

To grant an access permission to a content URI returned from  getUriForFile() , do one of the following:

Serving a Content URI to Another App

There are a variety of ways to serve the content URI for a file to a client app. One common way is for the client app to start your app by callingstartActivityResult(), which sends an Intent to your app to start an Activity in your app. In response, your app can immediately return a content URI to the client app or present a user interface that allows the user to pick a file. In the latter case, once the user picks the file your app can return its content URI. In both cases, your app returns the content URI in an Intent sent via setResult().

You can also put the content URI in a ClipData object and then add the object to an Intent you send to a client app. To do this, callIntent.setClipData(). When you use this approach, you can add multiple ClipData objects to the Intent, each with its own content URI. When you callIntent.setFlags() on the Intent to set temporary access permissions, the same permissions are applied to all of the content URIs.

Note: The Intent.setClipData() method is only available in platform version 16 (Android 4.1) and later. If you want to maintain compatibility with previous versions, you should send one content URI at a time in the Intent. Set the action to ACTION_SEND and put the URI in data by callingsetData().









猜你喜欢

转载自blog.csdn.net/hhbbeijing/article/details/52786257