Although a rare circumstance, sometime you might want to share a document, or an image or audio file from your app’s resources directory, without having to save it, because we don’t want to have to ask for the read and write external storage permissions just for that.

There’s an awesome library that makes this easy. You can go ahead and explore it, I wrote this blog to jot down a simple example for this.

Adding the library

build.gradle

repositories {
    maven {
        url "https://s3.amazonaws.com/repo.commonsware.com"
    }
}

dependencies {
    compile 'com.commonsware.cwac:provider:0.5.3'
}

AndroidManifest.xml

<provider
    android:name="com.commonsware.cwac.provider.StreamProvider"
    android:authorities="com.yourpackage.AssetProvider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="com.commonsware.cwac.provider.STREAM_PROVIDER_PATHS"
        android:resource="@xml/files_meta" />
</provider>

Sharing an audio file from res/raw

First, we need to create the meta XML file.

res/xml/files_meta.xml

Create a raw-resource tag for each file, with name and path as the audio file name without the extension. The name can be any unique identifier, but we will use the audio file name here for simplicity.

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <raw-resource
        name="myaudfile1"        
        path="myaudfile1"/>
    <raw-resource
        name="myaudfile2"
        path="myaudfile2"/>
</paths>

Code in your activity for sharing the file:

String COMMON_AUTHORITY = "com.yourpackage.AssetProvider";
Uri uri = Uri.parse("content://" + COMMON_AUTHORITY)
        .buildUpon()
        .appendPath(StreamProvider.getUriPrefix(COMMON_AUTHORITY))
        .appendPath("myaudfile1") //the name attribute
        .appendPath("myaudfile1.mp3") //the path attribute, + extension
        .build();

Intent share = new Intent(Intent.ACTION_SEND);
share.setType("audio/*");
share.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(Intent.createChooser(share, "Share Audio File"));

For sharing multiple audio files at once

String COMMON_AUTHORITY = "com.yourpackage.AssetProvider";

ArrayList<Uri> uris = new ArrayList<Uri>();

for (String file: filenames) {
    Uri uri = Uri.parse("content://" + COMMON_AUTHORITY)
            .buildUpon()
            .appendPath(StreamProvider.getUriPrefix(COMMON_AUTHORITY))
            .appendPath(file)
            .appendPath(file+".mp3")
            .build();
    uris.add(uri);
}


Intent share = new Intent(Intent.ACTION_SEND_MULTIPLE);
share.setType("audio/*");
share.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);

startActivity(Intent.createChooser(share, "Share audios"));

Sharing a PDF from res/assets

Coming soon.