FileProvider

Added in 1.1.0

public class FileProvider extends ContentProvider


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:

  1. Defining a FileProvider
  2. Specifying Available Files
  3. Generating the Content URI for a File
  4. Granting Temporary Permissions to a URI
  5. Serving a Content URI to Another App

Defining a FileProvider

Extend FileProvider with a default constructor, and call super with an XML resource file that specifies the available files (see below for the structure of the XML file):

public class MyFileProvider extends FileProvider {
   public MyFileProvider() {
       super(R.xml.file_paths)
   }
}
Add a <provider> element to your app manifest. Set the android:name attribute to the FileProvider you created. 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="com.sample.MyFileProvider"
           android:authorities="com.mydomain.fileprovider"
           android:exported="false"
           android:grantUriPermissions="true">
           ...
       </provider>
       ...
   </application>
</manifest>

It is possible to use FileProvider directly instead of extending it. However, this is not reliable and will causes crashes on some devices.

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 by Context.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(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, the path 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, pass it to super() in the constructor for the FileProvider you defined above, add a 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="com.sample.MyFileProvider" 
 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(), "my_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(), you can either grant the permission to a specific package or include the permission in an intent, as shown in the following sections.

Grant Permission to a Specific Package

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.

Include the Permission in an Intent

To allow the user to choose which app receives the intent, and the permission to access the content, do the following:

  1. Put the content URI in an Intent by calling setData().
  2. Call the method Intent.setFlags() with either FLAG_GRANT_READ_URI_PERMISSION or FLAG_GRANT_WRITE_URI_PERMISSION or both.

    To support devices that run a version between Android 4.1 (API level 16) and Android 5.1 (API level 22) inclusive, create a ClipData object from the content URI, and set the access permissions on the ClipData object:

     shareContentIntent.setClipData(ClipData.newRawUri("", contentUri)); 
     shareContentIntent.addFlags( 
     Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 
     
  3. 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().

More Information

To learn more about FileProvider, see the Android training class Sharing Files Securely with URIs.

Summary

Public constructors

Protected constructors

FileProvider(@XmlRes int resourceId)

Public methods

void

After the FileProvider is instantiated, this method is called to provide the system with information about the provider.

int
delete(
    @NonNull Uri uri,
    @Nullable String selection,
    @Nullable String[] selectionArgs
)

Deletes the file associated with the specified content URI, as returned by getUriForFile().

@Nullable String

Returns the MIME type of a content URI returned by getUriForFile().

@Nullable String

Unrestricted version of getType called, when caller does not have corresponding permissions

static Uri
getUriForFile(
    @NonNull Context context,
    @NonNull String authority,
    @NonNull File file
)

Return a content URI for a given File.

static @NonNull Uri
getUriForFile(
    @NonNull Context context,
    @NonNull String authority,
    @NonNull File file,
    @NonNull String displayName
)

Return a content URI for a given File.

Uri

By default, this method throws an UnsupportedOperationException.

boolean

The default FileProvider implementation does not need to be initialized.

ParcelFileDescriptor

By default, FileProvider automatically returns the ParcelFileDescriptor for a file associated with a content://Uri.

@NonNull Cursor
query(
    @NonNull Uri uri,
    @Nullable String[] projection,
    @Nullable String selection,
    @Nullable String[] selectionArgs,
    @Nullable String sortOrder
)

Use a content URI returned by getUriForFile() to get information about a file managed by the FileProvider.

int
update(
    @NonNull Uri uri,
    @NonNull ContentValues values,
    @Nullable String selection,
    @Nullable String[] selectionArgs
)

By default, this method throws an UnsupportedOperationException.

Inherited Constants

From android.content.ComponentCallbacks2
static final int
static final int
static final int
static final int
static final int
static final int
static final int

Inherited methods

From android.content.ContentProvider
ContentProviderResult[]
applyBatch(
    String authority,
    ArrayList<ContentProviderOperation> operations
)
int
bulkInsert(Uri uri, ContentValues[] values)
Bundle
call(String authority, String method, String arg, Bundle extras)
Uri
final ContentProvider.CallingIdentity
void
dump(FileDescriptor fd, PrintWriter writer, String[] args)
final AttributionSource
final String
final String
final String
final Context
final PathPermission[]
final String
String[]
getStreamTypes(Uri uri, String mimeTypeFilter)
final String
boolean
void
void
void
void
onTrimMemory(int level)
AssetFileDescriptor
openAssetFile(Uri uri, String mode)
final ParcelFileDescriptor
openFileHelper(Uri uri, String mode)
ParcelFileDescriptor
<T> openPipeHelper(
    Uri uri,
    String mimeType,
    Bundle opts,
    T args,
    ContentProvider.PipeDataWriter<T> func
)
AssetFileDescriptor
openTypedAssetFile(Uri uri, String mimeTypeFilter, Bundle opts)
boolean
refresh(Uri uri, Bundle extras, CancellationSignal cancellationSignal)
final Context
final void
final void
setPathPermissions(PathPermission[] permissions)
final void
final void
void
Uri

Public constructors

FileProvider

Added in 1.1.0
public FileProvider()

Protected constructors

FileProvider

Added in 1.8.0
protected FileProvider(@XmlRes int resourceId)

Public methods

attachInfo

@CallSuper
public void attachInfo(@NonNull Context context, @NonNull ProviderInfo info)

After the FileProvider is instantiated, this method is called to provide the system with information about the provider.

Parameters
@NonNull Context context

A Context for the current component.

@NonNull ProviderInfo info

A ProviderInfo for the new provider.

delete

Added in 1.1.0
public int delete(
    @NonNull Uri uri,
    @Nullable String selection,
    @Nullable String[] selectionArgs
)

Deletes the file associated with the specified content URI, as returned by getUriForFile(). Notice that this method does not throw an IOException; you must check its return value.

Parameters
@NonNull Uri uri

A content URI for a file, as returned by getUriForFile().

@Nullable String selection

Ignored. Set to null.

@Nullable String[] selectionArgs

Ignored. Set to null.

Returns
int

1 if the delete succeeds; otherwise, 0.

getType

Added in 1.1.0
public @Nullable String getType(@NonNull Uri uri)

Returns the MIME type of a content URI returned by getUriForFile().

Parameters
@NonNull Uri uri

A content URI returned by getUriForFile().

Returns
@Nullable String

If the associated file has an extension, the MIME type associated with that extension; otherwise application/octet-stream.

getTypeAnonymous

Added in 1.11.0
public @Nullable String getTypeAnonymous(@NonNull Uri uri)

Unrestricted version of getType called, when caller does not have corresponding permissions

getUriForFile

Added in 1.1.0
public static Uri getUriForFile(
    @NonNull Context context,
    @NonNull String authority,
    @NonNull File file
)

Return a content URI for a given File. Specific temporary permissions for the content URI can be set with grantUriPermission, or added to an Intent by calling setData() and then setFlags(); in both cases, the applicable flags are FLAG_GRANT_READ_URI_PERMISSION and FLAG_GRANT_WRITE_URI_PERMISSION. A FileProvider can only return a contentUri for file paths defined in their <paths> meta-data element. See the Class Overview for more information.

Parameters
@NonNull Context context

A Context for the current component.

@NonNull String authority

The authority of a FileProvider defined in a <provider> element in your app's manifest.

@NonNull File file

A File pointing to the filename for which you want a contentUri.

Returns
Uri

A content URI for the file.

Throws
java.lang.IllegalArgumentException

When the given File is outside the paths supported by the provider.

getUriForFile

Added in 1.5.0
public static @NonNull Uri getUriForFile(
    @NonNull Context context,
    @NonNull String authority,
    @NonNull File file,
    @NonNull String displayName
)

Return a content URI for a given File. Specific temporary permissions for the content URI can be set with grantUriPermission, or added to an Intent by calling setData() and then setFlags(); in both cases, the applicable flags are FLAG_GRANT_READ_URI_PERMISSION and FLAG_GRANT_WRITE_URI_PERMISSION. A FileProvider can only return a contentUri for file paths defined in their <paths> meta-data element. See the Class Overview for more information.

Parameters
@NonNull Context context

A Context for the current component.

@NonNull String authority

The authority of a FileProvider defined in a <provider> element in your app's manifest.

@NonNull File file

A File pointing to the filename for which you want a contentUri.

@NonNull String displayName

The filename to be displayed. This can be used if the original filename is undesirable.

Returns
@NonNull Uri

A content URI for the file.

Throws
java.lang.IllegalArgumentException

When the given File is outside the paths supported by the provider.

insert

Added in 1.1.0
public Uri insert(@NonNull Uri uri, @NonNull ContentValues values)

By default, this method throws an UnsupportedOperationException. You must subclass FileProvider if you want to provide different functionality.

onCreate

Added in 1.1.0
public boolean onCreate()

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

public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode)

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
@NonNull Uri uri

A content URI associated with a file, as returned by getUriForFile().

@NonNull String mode

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.

Returns
ParcelFileDescriptor

A new ParcelFileDescriptor with which you can access the file.

query

Added in 1.1.0
public @NonNull Cursor query(
    @NonNull Uri uri,
    @Nullable String[] projection,
    @Nullable String selection,
    @Nullable String[] selectionArgs,
    @Nullable String sortOrder
)

Use a content URI returned by getUriForFile() to get information about a file managed by the FileProvider. FileProvider reports the column names defined in OpenableColumns:

For more information, see ContentProvider.query().
Parameters
@NonNull Uri uri

A content URI returned by getUriForFile.

@Nullable String[] projection

The list of columns to put into the Cursor. If null all columns are included.

@Nullable String selection

Selection criteria to apply. If null then all data that matches the content URI is returned.

@Nullable String[] selectionArgs

An array of 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 String values.

@Nullable String sortOrder

A String containing the column name(s) on which to sort the resulting Cursor.

Returns
@NonNull Cursor

A Cursor containing the results of the query.

update

Added in 1.1.0
public int update(
    @NonNull Uri uri,
    @NonNull ContentValues values,
    @Nullable String selection,
    @Nullable String[] selectionArgs
)

By default, this method throws an UnsupportedOperationException. You must subclass FileProvider if you want to provide different functionality.