FileProvider
open class FileProvider : ContentProvider
kotlin.Any | ||
↳ | android.content.ContentProvider | |
↳ | androidx.core.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 android.app.Activity
is active. For an Intent
going to a android.app.Service
, the permissions are available as long as the android.app.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 androidx.core.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="androidx.core.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>
The <paths>
element must contain one or more of the following child elements:
-
<files-path name="<i>name</i>" path="<i>path</i>" />
- 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="<i>name</i>" path="<i>path</i>" />
- 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="<i>name</i>" path="<i>path</i>" />
- 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="<i>name</i>" path="<i>path</i>" />
- 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="<i>name</i>" path="<i>path</i>" />
- 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="<i>name</i>" path="<i>path</i>" />
- 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="androidx.core.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 android.content.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 fromgetUriForFile()
, do one of the following:
- Call the method
Context.grantUriPermission(package, Uri, mode_flags)
for thecontent://
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 themode_flags
parameter, which you can set toIntent#FLAG_GRANT_READ_URI_PERMISSION
,Intent#FLAG_GRANT_WRITE_URI_PERMISSION
or both. The permission remains in effect until you revoke it by callingrevokeUriPermission()
or until the device reboots. - Put the content URI in an
Intent
by callingsetData()
. - Next, call the method
Intent.setFlags()
with eitherIntent#FLAG_GRANT_READ_URI_PERMISSION
orIntent#FLAG_GRANT_WRITE_URI_PERMISSION
or both. - Finally, send the
Intent
to another app. Most often, you do this by callingsetResult()
.Permissions granted in an
Intent
remain in effect while the stack of the receivingandroid.app.Activity
is active. When the stack finishes, the permissions are automatically removed. Permissions granted to oneandroid.app.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 android.app.Activity#startActivityForResult(Intent, int, Bundle), which sends an Intent
to your app to start an android.app.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 android.content.ClipData
object and then add the object to an Intent
you send to a client app. To do this, call Intent#setClipData(ClipData). When you use this approach, you can add multiple android.content.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(ClipData) 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 Intent#ACTION_SEND
and put the URI in data by calling setData()
.
More Information
To learn more about FileProvider, see the Android training class Sharing Files Securely with URIs.
Summary
Public constructors |
|
---|---|
<init>() FileProvider is a special subclass of |
Public methods |
|
---|---|
open Unit |
attachInfo(@NonNull context: Context, @NonNull info: ProviderInfo) After the FileProvider is instantiated, this method is called to provide the system with information about the provider. |
open Int |
Deletes the file associated with the specified content URI, as returned by |
open String! |
Returns the MIME type of a content URI returned by |
open static Uri! |
getUriForFile(@NonNull context: Context, @NonNull authority: String, @NonNull file: File) Return a content URI for a given |
open Uri! |
insert(@NonNull uri: Uri, values: ContentValues!) By default, this method throws an |
open Boolean |
onCreate() The default FileProvider implementation does not need to be initialized. |
open ParcelFileDescriptor! |
By default, FileProvider automatically returns the |
open Cursor! |
query(@NonNull uri: Uri, @Nullable projection: Array<String!>?, @Nullable selection: String?, @Nullable selectionArgs: Array<String!>?, @Nullable sortOrder: String?) Use a content URI returned by |
open Int |
update(@NonNull uri: Uri, values: ContentValues!, @Nullable selection: String?, @Nullable selectionArgs: Array<String!>?) By default, this method throws an |
Public constructors
<init>
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 android.app.Activity
is active. For an Intent
going to a android.app.Service
, the permissions are available as long as the android.app.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 androidx.core.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="androidx.core.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>
The <paths>
element must contain one or more of the following child elements:
-
<files-path name="<i>name</i>" path="<i>path</i>" />
- 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="<i>name</i>" path="<i>path</i>" />
- 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="<i>name</i>" path="<i>path</i>" />
- 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="<i>name</i>" path="<i>path</i>" />
- 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="<i>name</i>" path="<i>path</i>" />
- 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="<i>name</i>" path="<i>path</i>" />
- 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="androidx.core.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 android.content.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 fromgetUriForFile()
, do one of the following:
- Call the method
Context.grantUriPermission(package, Uri, mode_flags)
for thecontent://
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 themode_flags
parameter, which you can set toIntent#FLAG_GRANT_READ_URI_PERMISSION
,Intent#FLAG_GRANT_WRITE_URI_PERMISSION
or both. The permission remains in effect until you revoke it by callingrevokeUriPermission()
or until the device reboots. - Put the content URI in an
Intent
by callingsetData()
. - Next, call the method
Intent.setFlags()
with eitherIntent#FLAG_GRANT_READ_URI_PERMISSION
orIntent#FLAG_GRANT_WRITE_URI_PERMISSION
or both. - Finally, send the
Intent
to another app. Most often, you do this by callingsetResult()
.Permissions granted in an
Intent
remain in effect while the stack of the receivingandroid.app.Activity
is active. When the stack finishes, the permissions are automatically removed. Permissions granted to oneandroid.app.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 android.app.Activity#startActivityForResult(Intent, int, Bundle), which sends an Intent
to your app to start an android.app.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 android.content.ClipData
object and then add the object to an Intent
you send to a client app. To do this, call Intent#setClipData(ClipData). When you use this approach, you can add multiple android.content.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(ClipData) 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 Intent#ACTION_SEND
and put the URI in data by calling setData()
.
More Information
To learn more about FileProvider, see the Android training class Sharing Files Securely with URIs.
Public methods
attachInfo
open fun attachInfo(@NonNull context: Context, @NonNull info: ProviderInfo): Unit
After the FileProvider is instantiated, this method is called to provide the system with information about the provider.
Parameters | |
---|---|
context |
Context: A Context for the current component. |
info |
Context: A ProviderInfo for the new provider. |
delete
open fun delete(@NonNull uri: Uri, @Nullable selection: String?, @Nullable selectionArgs: Array<String!>?): Int
Deletes the file associated with the specified content URI, as returned by getUriForFile()
. Notice that this method does not throw an java.io.IOException
; you must check its return value.
Parameters | |
---|---|
uri |
Uri: A content URI for a file, as returned by getUriForFile() . |
selection |
Uri: Ignored. Set to null . |
selectionArgs |
Uri: Ignored. Set to null . |
Return | |
---|---|
Int: 1 if the delete succeeds; otherwise, 0. |
getType
open fun getType(@NonNull uri: Uri): String!
Returns the MIME type of a content URI returned by getUriForFile()
.
Parameters | |
---|---|
uri |
Uri: A content URI returned by getUriForFile() . |
Return | |
---|---|
String!: If the associated file has an extension, the MIME type associated with that extension; otherwise application/octet-stream . |
getUriForFile
open static fun getUriForFile(@NonNull context: Context, @NonNull authority: String, @NonNull file: File): Uri!
Return a content URI for a given File
. Specific temporary permissions for the content URI can be set with Context#grantUriPermission(String, Uri, int)
, or added to an Intent
by calling setData()
and then setFlags()
; in both cases, the applicable flags are Intent#FLAG_GRANT_READ_URI_PERMISSION
and Intent#FLAG_GRANT_WRITE_URI_PERMISSION
. A FileProvider can only return a content
Uri
for file paths defined in their <paths>
meta-data element. See the Class Overview for more information.
Parameters | |
---|---|
context |
Context: A Context for the current component. |
authority |
Context: The authority of a FileProvider defined in a <provider> element in your app's manifest. |
file |
Context: A File pointing to the filename for which you want a content Uri . |
Return | |
---|---|
Uri!: A content URI for the file. |
Exceptions | |
---|---|
IllegalArgumentException |
When the given File is outside the paths supported by the provider. |
insert
open fun insert(@NonNull uri: Uri, values: ContentValues!): Uri!
By default, this method throws an java.lang.UnsupportedOperationException
. You must subclass FileProvider if you want to provide different functionality.
onCreate
open fun onCreate(): Boolean
The default FileProvider implementation does not need to be initialized. If you want to override this method, you must provide your own subclass of FileProvider.
openFile
open fun openFile(@NonNull uri: Uri, @NonNull mode: String): ParcelFileDescriptor!
By default, FileProvider automatically returns the ParcelFileDescriptor
for a file associated with a content://
Uri
. To get the ParcelFileDescriptor
, call ContentResolver.openFileDescriptor
. To override this method, you must provide your own subclass of FileProvider.
Parameters | |
---|---|
uri |
Uri: A content URI associated with a file, as returned by getUriForFile() . |
mode |
Uri: Access mode for the file. May be "r" for read-only access, "rw" for read and write access, or "rwt" for read and write access that truncates any existing file. |
Return | |
---|---|
ParcelFileDescriptor!: A new ParcelFileDescriptor with which you can access the file. |
query
open fun query(@NonNull uri: Uri, @Nullable projection: Array<String!>?, @Nullable selection: String?, @Nullable selectionArgs: Array<String!>?, @Nullable sortOrder: String?): Cursor!
Use a content URI returned by getUriForFile()
to get information about a file managed by the FileProvider. FileProvider reports the column names defined in android.provider.OpenableColumns
:
ContentProvider.query()
.
Parameters | |
---|---|
uri |
Uri: A content URI returned by getUriForFile . |
projection |
Uri: The list of columns to put into the Cursor . If null all columns are included. |
selection |
Uri: Selection criteria to apply. If null then all data that matches the content URI is returned. |
selectionArgs |
Uri: An array of java.lang.String , containing arguments to bind to the selection parameter. The query method scans selection from left to right and iterates through selectionArgs, replacing the current "?" character in selection with the value at the current position in selectionArgs. The values are bound to selection as java.lang.String values. |
sortOrder |
Uri: A java.lang.String containing the column name(s) on which to sort the resulting Cursor . |
Return | |
---|---|
Cursor!: A Cursor containing the results of the query. |
update
open fun update(@NonNull uri: Uri, values: ContentValues!, @Nullable selection: String?, @Nullable selectionArgs: Array<String!>?): Int
By default, this method throws an java.lang.UnsupportedOperationException
. You must subclass FileProvider if you want to provide different functionality.