public class PublicFileProvider extends ContentProvider
ContentProvider that facilitates exposing files associated with
an app by creating a content:// Uri for a file instead of a file:/// Uri.
WARNING: Most of the time this is NOT what you want. Use FileProvider to only grant temporary access to files, e.g. when sharing content to other apps.
PublicFileProvider is a modified version of FileProvider with the specific goal to expose files without using
Android's URI permission mechanism. This can come in handy when you have to provide a content:// URI but
can't easily grant read access to whatever app ends up accessing the content.
One use case is a custom ringtone in a notification. Check out the blog post
Notifications,
Sounds, Android 7.0, and Aggravation for more details.
This overview of PublicFileProvider includes the following topics:
Since the default functionality of PublicFileProvider includes content URI generation for files, you
don't need to define a subclass in code. Instead, you can include a PublicFileProvider in your app
by specifying it entirely in XML. To specify the PublicFileProvider component itself, add a
<provider>
element to your app manifest. Set the android:name attribute to
de.cketti.fileprovider.PublicFileProvider. 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.publicfileprovider. Set the android:exported attribute to
true. For example:
<manifest>
...
<application>
...
<provider
android:name="de.cketti.fileprovider.PublicFileProvider"
android:authorities="com.mydomain.publicfileprovider"
android:exported="true">
...
</provider>
...
</application>
</manifest>
You can override some of the default behavior of PublicFileProvider by extending the PublicFileProvider class. If you
do so, use the fully-qualified class name in the android:name
attribute of the <provider> element.
<paths> element.
For example, the following paths element tells PublicFileProvider 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_notification_sounds" path="notification_sounds/"/>
...
</paths>
The <paths> element must contain one or more of the following child elements:
<files-path name="name" path="path" />
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" />
getCacheDir().
<external-path name="name" path="path" />
Environment.getExternalStorageDirectory().
<external-files-path name="name" path="path" />
Context#getExternalFilesDir(String) Context.getExternalFilesDir(null).
<external-cache-path name="name" path="path" />
Context.getExternalCacheDir().
These child elements all use the same attributes:
name="name"
path attribute.
path="path"
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/publicfileprovider_paths.xml.
To link this file to the PublicFileProvider, add a
<meta-data> element
as a child of the <provider> element that defines the PublicFileProvider. Set the
<meta-data> element's "android:name" attribute to
de.cketti.fileprovider.PUBLIC_FILE_PROVIDER_PATHS. Set the element's "android:resource" attribute
to @xml/publicfileprovider_paths (notice that you don't specify the .xml
extension). For example:
<provider
android:name="de.cketti.fileprovider.PublicFileProvider"
android:authorities="com.mydomain.publicfileprovider"
android:exported="true">
<meta-data
android:name="de.cketti.fileprovider.PUBLIC_FILE_PROVIDER_PATHS"
android:resource="@xml/publicfileprovider_paths" />
</provider>
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 PublicFileProvider that has the
authority com.mydomain.publicfileprovider. 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.publicfileprovider", newFile);As a result of the previous snippet,
getUriForFile() returns the content URI
content://com.mydomain.publicfileprovider/my_images/default_image.jpg.ContentProvider.PipeDataWriter<T>TRIM_MEMORY_BACKGROUND, TRIM_MEMORY_COMPLETE, TRIM_MEMORY_MODERATE, TRIM_MEMORY_RUNNING_CRITICAL, TRIM_MEMORY_RUNNING_LOW, TRIM_MEMORY_RUNNING_MODERATE, TRIM_MEMORY_UI_HIDDEN| Constructor and Description |
|---|
PublicFileProvider() |
| Modifier and Type | Method and Description |
|---|---|
void |
attachInfo(Context context,
ProviderInfo info)
After the PublicFileProvider is instantiated, this method is called to provide the system with
information about the provider.
|
int |
delete(Uri uri,
String selection,
String[] selectionArgs) |
String |
getType(Uri uri)
Returns the MIME type of a content URI returned by
getUriForFile(). |
static Uri |
getUriForFile(Context context,
String authority,
File file)
Return a content URI for a given
File. |
Uri |
insert(Uri uri,
ContentValues values) |
boolean |
onCreate()
The default PublicFileProvider implementation does not need to be initialized.
|
AssetFileDescriptor |
openAssetFile(Uri uri,
String mode) |
AssetFileDescriptor |
openAssetFile(Uri uri,
String mode,
CancellationSignal signal) |
ParcelFileDescriptor |
openFile(Uri uri,
String mode) |
ParcelFileDescriptor |
openFile(Uri uri,
String mode,
CancellationSignal signal) |
Cursor |
query(Uri uri,
String[] projection,
String selection,
String[] selectionArgs,
String sortOrder)
Use a content URI returned by
getUriForFile() to get information about a file
managed by the PublicFileProvider. |
int |
update(Uri uri,
ContentValues values,
String selection,
String[] selectionArgs) |
applyBatch, bulkInsert, call, canonicalize, dump, getCallingPackage, getContext, getPathPermissions, getReadPermission, getStreamTypes, getWritePermission, isTemporary, onConfigurationChanged, onLowMemory, onTrimMemory, openFileHelper, openPipeHelper, openTypedAssetFile, openTypedAssetFile, query, setPathPermissions, setReadPermission, setWritePermission, shutdown, uncanonicalizepublic boolean onCreate()
onCreate in class ContentProviderpublic void attachInfo(Context context, ProviderInfo info)
attachInfo in class ContentProvidercontext - A Context for the current component.info - A ProviderInfo for the new provider.public static Uri getUriForFile(Context context, String authority, File file)
File. A PublicFileProvider can only return a
content Uri for file paths defined in their <paths>
meta-data element. See the Class Overview for more information.context - A Context for the current component.authority - The authority of a PublicFileProvider defined in a
<provider> element in your app's manifest.file - A File pointing to the filename for which you want a
content Uri.IllegalArgumentException - When the given File is outside
the paths supported by the provider.public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
getUriForFile() to get information about a file
managed by the PublicFileProvider.
PublicFileProvider reports the column names defined in OpenableColumns:
For more information, see
ContentProvider.query().query in class ContentProvideruri - A content URI returned by getUriForFile(android.content.Context, java.lang.String, java.io.File).projection - The list of columns to put into the Cursor. If null all columns are
included.selection - Selection criteria to apply. If null then all data that matches the content
URI is returned.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.sortOrder - A String containing the column name(s) on which to sort
the resulting Cursor.Cursor containing the results of the query.public String getType(Uri uri)
getUriForFile().getType in class ContentProvideruri - A content URI returned by
getUriForFile().application/octet-stream.public final Uri insert(Uri uri, ContentValues values)
insert in class ContentProviderpublic final int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
update in class ContentProviderpublic final int delete(Uri uri, String selection, String[] selectionArgs)
delete in class ContentProviderpublic final ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException
openFile in class ContentProviderFileNotFoundExceptionpublic final ParcelFileDescriptor openFile(Uri uri, String mode, CancellationSignal signal) throws FileNotFoundException
openFile in class ContentProviderFileNotFoundExceptionpublic final AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException
openAssetFile in class ContentProviderFileNotFoundExceptionpublic final AssetFileDescriptor openAssetFile(Uri uri, String mode, CancellationSignal signal) throws FileNotFoundException
openAssetFile in class ContentProviderFileNotFoundException