Storing files privately on Android and opening them using an external application.

This blog will be divided into two parts. First, how can we store files in the private storage of our Android application so that it is not directly accessible by other applications running on the device, such as the file manager and second, how to open these files using an external application.

Step 1 : Saving private application files.

Beginning with Android 4.4, reading or writing files in the app’s private directories does not require the READ_EXTERNAL_STORAGE or WRITE_EXTERNAL_STORAGE permissions. So the permission should be requested only on lower versions of Android.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
                     android:maxSdkVersion="18" />

Retrieving private file storage directory :

public String getPrivateFileStoragePath(Context mContext) {
    return mContext.getFilesDir().getAbsolutePath();
}

The above method will return the private storage directory’s absolute path. Now we can start saving files to the above directory.

String privateFileStoragePath = getPrivateFilesStoragePath(context);
File outputFile = new File(privateFileStoragePath + "sample_file.txt");
//Relevant code to write file to the directory goes here. 

Step 2 : Opening private file using another android application

Now, let’s suppose this is a file type that is not supported by our application. Let’s consider a pdf file. Given that there is a viewer already installed on the phone which supports pdf files, all we need to do is launch an intent with the file path and it’ll automatically open in the pdf viewer. But the issue here is that the files are stored in the private storage of our application and external applications cannot access it, so launching the intent with the file path is not going to work.

In this case, we’ll use a ContentProvider. A content provider allows us to securely provide our data to other applications.

First of all, we need to declare the content provider in the manifest.

<provider
    android:name="SampleContentProvider"
    android:authorities="com.sample.provider"
    android:exported="true" />        

Here, name is the class name of the content provider, authorities is the URI authority that is used to access data via the content provider and setting exported to true allows other applications to use this content provider. More details here.

Finally, we write the content provider class.

public class SampleContentProvider extends ContentProvider {

    @Override
    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
        File privateFile = new File(uri.getPath());
        return ParcelFileDescriptor.open(privateFile, ParcelFileDescriptor.MODE_READ_ONLY);
    }

    @Override
    public boolean onCreate() {
        return false;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        return null;
    }

    @Override
    public String getType(Uri uri) {
        return null;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        return null;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        return 0;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        return 0;
    }
}

The openFile() method here has to take care of the fact that it returns the correct file descriptor on receiving a request.

Now, when launching the intent :

    Intent intent = new Intent(Intent.ACTION_VIEW);
    String absoluteFilePath = ...;
    String mimeType = "application/pdf";
    Uri uri = Uri.parse("content://com.sample.provider/" + absoluteFilePath);
    //Here com.sample.provider is the authority defined in the manifest. 
    intent.setDataAndType(uri, mimeType);
    startActivity(intent);

This will allow other apps to access the private pdf file via the content provider 🙂

Advertisements

One thought on “Storing files privately on Android and opening them using an external application.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s