How to Share Files Securely with FileProvider

 

1 Star2 Stars3 Stars4 Stars5 Stars (2 votes, average: 5.00 out of 5)
Loading...

 

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.

 FileProvider

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.

Recommended Posts
Contact Us

We look forward to your messages. Please drop us a note for any enquiries and we'll get back to you, asap.

Not readable? Change text. captcha txt
Neural NetworkDeep Learning Video