Contents
Tung Dao Xuan, tungdx1210@gmail.com, is the author of this article and he contributes to RobustTechHouse Blog
Introduction
FileProvider is a special subclass of ContentProvider that facilitates secure sharing of files associated with an app by creating a content:// Uri (Uniform Resource Identifier) for a file instead of a file:/// Uri. To find out why we should use this class to share the files managed by your application with other applications, you can check it here.
In this tutorial, we are going to create an application to demonstrate how to use FileProvider for file sharing.
Creating an application
This application has one button each to save a file to internal storage, cache folder and external storage. The three buttons shown in the diagram below corresponds to the above mentioned features to demonstrate sharing files in three locations. Please take a look at following diagram for more clarity.
Saving a file to multiple locations
private void saveFileToMultipleLocations(Context context) { String content = "Share files using FileProvider!"; //save to external storage saveFile(content, getFile(context.getExternalFilesDir(null), FILE_NAME)); //save to internal storage saveFile(content, getFile(context.getFilesDir(), FILE_NAME)); //save to cache directory saveFile(content, getFile(context.getCacheDir(), FILE_NAME)); } private File getFile(File root, String fileName) { File folder = new File(root, FOLDER_NAME); if (!folder.exists()) { folder.mkdirs(); } return new File(folder, fileName); } private void saveFile(String data, File out) { try { FileWriter writer = new FileWriter(out); writer.write(data); writer.flush(); writer.close(); } catch (IOException e) { e.printStackTrace(); } }
Defining a FileProvider
Since the default functionality of FileProvider includes content URI generation for files, you don’t need to define a subclass in the codes. Instead, you can include a FileProvider in your app by specifying it entirely in XML in the AndroidManifest.xml file.
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <provider android:name="android.support.v4.content.FileProvider" android:authorities="vn.tungdx.filesharing.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider> </application>
Note:
- Set the android:authorities attribute to a URI authority based on a domain you control; for example, if you control the domain com you should use the authority com.mydomain.fileprovider.
- Set the android:resource to a xml file that specifies the available files. This file will be created in next section.
Specifying Available Files
Create file_paths.xml file in folder res/xml in the project that contains following content:
<?xml version="1.0" encoding="utf-8"?> <paths> <files-path name="internal_docs" path="docs/" /> <external-path name="external_docs" path="Android/data/vn.tungdx.filesharing/files/docs/" /> <cache-path name="cache_docs" path="docs/" /> </paths>
<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().
<external-path name="name" path="path" />
Represents files in the root of your app’s external storage area. The path Context.getExternalFilesDir() returns the files/ subdirectory of this root.
<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()
The attributes:
name=“name”
A URI path segment. 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.
Sharing a file
static final String AUTHORITIES_NAME = "vn.tungdx.filesharing.fileprovider"; private void share(File fileSharing) { Uri contentUri = FileProvider.getUriForFile(getApplicationContext(), AUTHORITIES_NAME, fileSharing); Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(contentUri); intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); startActivity(intent); }
This variable AUTHORITIES_NAME must be equal to name that is specified in the android:authorities attribute in the provider above.
Intent.FLAG_GRANT_READ_URI_PERMISSION the recipient of this Intent will be granted permission to perform read operations on the URI in the Intent’s data.
Source code
https://github.com/tungdx/FileSharingUsingFileProvider.git
Brought to you by RobustTechHouse. We provide E-Commerce Development services.
A URI path segment. This value hides the name of the subdirectory you’re sharing. The subdirectory name for this value is contained in the path attribute.
Thanks for the useful information from your article