您的位置:首页 > 移动开发 > Android开发

FileProvider android 7 文件共享

2016-10-11 11:34 441 查看
翻译成人话比较难,还是尝试阅读原版吧!

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 the
android: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 the
android: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:
Call the method 
Context.grantUriPermission(package,
Uri, mode_flags)
 for the 
content://
 
Uri
, using the desired
mode flags. This grants temporary access permission for the content URI to the specified package, according to the value of the the 
mode_flags
 parameter, which you can set to 
FLAG_GRANT_READ_URI_PERMISSION
FLAG_GRANT_WRITE_URI_PERMISSION
 or
both. The permission remains in effect until you revoke it by calling
revokeUriPermission()
 or
until the device reboots.
Put the content URI in an 
Intent
 by calling 
setData()
.
Next, call the method 
Intent.setFlags()
 with
either 
FLAG_GRANT_READ_URI_PERMISSION
 or 
FLAG_GRANT_WRITE_URI_PERMISSION
 or
both.
Finally, send the 
Intent
 to another app. Most often, you
do this by calling 
setResult()
.
Permissions granted in an 
Intent
 remain in
effect while the stack of the receiving 
Activity
 is active. When the stack finishes, the
permissions are automatically removed. Permissions granted to one 
Activity
 in a client
app are automatically extended to other components of that app.

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 calling
startActivityResult()
,
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, call
Intent.setClipData()
.
When you use this approach, you can add multiple 
ClipData
 objects to the 
Intent
,
each with its own content URI. When you call
Intent.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 calling
setData()
.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: