Android content provider - share private app file content

In this post I will cover opening private application files in other applications. Here is an example to make the problem easier to grasp.

We have an app that stores pdf files in its private storage. Because Android doesn't provide a framework to deal with pdf files, and other external libraries (the few that are available) were too awkward to use, we decided to go with a third party application. Adobe Reader seems to be most efficient by far, but it's really up to the end user to use the app of his/her choice.

The topic is covered by content providers.

ContentProvider code to open the pdf files in other applications

public class FileContentProvider extends ContentProvider {
    private Context mContext;

    @Override
    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
        File file =  new File("path to file");

        if (file.exists()) {
            return (ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_WRITE));
        }
        throw new FileNotFoundException(uri.getPath());
    }

    @Override
    public boolean onCreate() {
        mContext = getContext();
        return true;
    }

    @Override
    public Cursor query(Uri uri, String[] strings, String s, String[] strings2, String s2) {
        throw new UnsupportedOperationException("Not supported by this provider");
    }

    @Override
    public String getType(Uri uri) {
        return "application/pdf";
    }

    @Override
    public Uri insert(Uri uri, ContentValues contentValues) {
        throw new UnsupportedOperationException("Not supported by this provider");
    }

    @Override
    public int delete(Uri uri, String s, String[] strings) {
        throw new UnsupportedOperationException("Not supported by this provider");
    }

    @Override
    public int update(Uri uri, ContentValues contentValues, String s, String[] strings) {
        throw new UnsupportedOperationException("Not supported by this provider");
    }
}

The important thing is to implement the openFile method, while other methods that are not being used should throw exception. We have to register this provider in our application, so we have to insert provider tag in android manifest (application tag):

<provider
android:name="com.example.app.FileContentProvider"
android:authorities="com.example.app.pdf"
android:exported="true" />

Next, we need to write the code for opening the pdf file in other apps.

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse("content://com.example.app.pdf/path"),
        "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
try {
    startActivity(intent);
} catch (ActivityNotFoundException e) {
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    builder.setTitle("App not found!");
    builder.setMessage("Download app");
    builder.setPositiveButton("Confirm",
        new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Intent marketIntent = new
                Intent(Intent.ACTION_VIEW);
                marketIntent.setData(Uri.parse("market://search?q=pdf"));
                try {
                    startActivity(marketIntent);
                }catch (ActivityNotFoundException e){}
            }
        }
    );
    builder.setNegativeButton("Cancel", null);
    builder.create().show();
}

The important part of the code is to set Data and Type:

intent.setDataAndType(Uri.parse("content://com.example.app.pdf/path"),"application/pdf").

You must specify the same Uri as in the android manifest provider above.

In case the device has no aplication that can handle pdf, an ActivityNotFoundException is thrown. We simply display a pop-up dialog to download an appropriate app from Google Play Store.

This is example code for opening the pdf files. To make it work other file types, you should be careful to specify appropriate file types, everything else should work as expected.