Search code examples
androidandroid-contentprovidercommonsware-cwacandroid-fileprovider

How to set up CWAC-Provider to be accessible from another app?


I'm relatively new to ContentProviders in Android and I liked the idea of sharing asset files between apps. Let's say I have 2 apps: AppA has all the nice images I want to access from AppB. AppA has StreamProvider set like this:

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

with assetpaths.xml like this:

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <asset name="assets" path="test"/>
</paths>

All works well and I can access my assets through StreamProvider in my AppA (getUriPrefix() for that authority returns some non-null value).

The difficult part begins when I try to access the assets from my AppB with this code:

String COMMON_AUTHORITY = "org.example.AssetProvider";
Uri test = Uri.parse("content://" + COMMON_AUTHORITY)
    .buildUpon()
    .appendPath(StreamProvider.getUriPrefix(COMMON_AUTHORITY))
    .appendPath("assets")
    .appendPath("test.jpg")
    .build();
InputStream is = getContentResolver().openInputStream(test)

The getUriPrefix() method returns null as there is no Provider registered in INSTANCES private field of StreamProvider class. When I wrote down the prefix from running this code in AppA and then hard-coded it AppB, it all went well and I could obtain an InputStream.

My questions are -

  1. Is there any way how I can access the prefix of my Authority from another app?
  2. Is there any other way I can access files stored in another app's APK file?

Thank you for your reply in advance! :)


Solution

  • In AppA, subclass StreamProvider and override getUriPrefix() to return null. Use the subclass in your <provider> element. Then, build the Uri in AppB without a prefix.

    BTW, you should be able to remove android:grantUriPermissions="true", as you are exporting this provider.