belongs to Maven artifact com.android.support:support-compat:28.0.0-alpha1
FileProvider
public
class
FileProvider
extends ContentProvider
java.lang.Object | ||
↳ | android.content.ContentProvider | |
↳ | android.support.v4.content.FileProvider |
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.
This overview of FileProvider includes the following topics:
- Defining a FileProvider
- Specifying Available Files
- Retrieving the Content URI for a File
- Granting Temporary Permissions to a URI
- Serving a Content URI to Another App
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 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>
The <paths>
element must contain one or more of the following child elements:
-
<files-path name="name" path="path" />
-
Represents files in the
files/
subdirectory of your app's internal storage area. This subdirectory is the same as the value returned byContext.getFilesDir()
. -
<cache-path name="name" path="path" />
-
Represents files in the cache subdirectory of your app's internal storage area. The root path
of this subdirectory is the same as the value returned by
getCacheDir()
. -
<external-path name="name" path="path" />
-
Represents files in the root of the external storage area. The root path of this subdirectory
is the same as the value returned by
Environment.getExternalStorageDirectory()
. -
<external-files-path name="name" path="path" />
-
Represents files in the root of your app's external storage area. The root path of this
subdirectory is the same as the value returned by
Context#getExternalFilesDir(String) Context.getExternalFilesDir(null)
. -
<external-cache-path name="name" path="path" />
-
Represents files in the root of your app's external cache area. The root path of this
subdirectory is the same as the value returned by
Context.getExternalCacheDir()
. -
<external-media-path name="name" path="path" />
-
Represents files in the root of your app's external media area. The root path of this
subdirectory is the same as the value returned by the first result of
Context.getExternalMediaDirs()
.Note: this directory is only available on API 21+ devices.
These child elements all use the same attributes:
-
name="name"
-
A URI path segment. To enforce security, this value hides the name of the subdirectory
you're sharing. The subdirectory name for this value is contained in the
path
attribute. -
path="path"
-
The subdirectory you're sharing. While the
name
attribute is a URI path segment, thepath
value is an actual subdirectory name. Notice that the value refers to a subdirectory, not an individual file or files. You can't share a single file by its file name, nor can you specify a subset of files using wildcards.
You must specify a child element of <paths>
for each directory that contains
files for which you want content URIs. For example, these XML elements specify two directories:
<paths xmlns:android="http://schemas.android.com/apk/res/android"> <files-path name="my_images" path="images/"/> <files-path name="my_docs" path="docs/"/> </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