Search code examples
androidandroid-intentandroid-contentprovider

Sharing an Image in app's data directory through a ContentProvider on Android


I'm trying to expose a .png file located in my application's /data directory through a ContentProvider but instead of reaching the openFile method query is being called. Now I only ever have a single image which I need to expose for sharing to other applications, how can I setup my Intent to goto openFile instead of query?

Intent shareImageIntent = new Intent(Intent.ACTION_SEND);

            shareImageIntent.setType("image/*");

            shareImageIntent.putExtra(Intent.EXTRA_STREAM, imageUri);
            startActivity(Intent.createChooser(shareImageIntent, "Share image"));

Where the Uri looks like

content://my.package.contentprovider/fileName

Or alternatively do I need to create a database for this and return a cursor?

UPDATE

So this appears to be working on everything except the SMS app (which is what I decided to test first) I would like to support sharing to it however.

Here's the relevant stack trace:

Caused by: java.lang.IllegalArgumentException: Query on content://mypackage.myprovider/someImage.png returns null result. at com.android.mms.ui.UriImage.initFromContentUri(UriImage.java:104) at com.android.mms.ui.UriImage.(UriImage.java:63) at com.android.mms.model.ImageModel.initModelFromUri(ImageModel.java:83) at com.android.mms.model.ImageModel.(ImageModel.java:65) at com.android.mms.data.WorkingMessage.changeMedia(WorkingMessage.java:481) at com.android.mms.data.WorkingMessage.setAttachment(WorkingMessage.java:375) ...

So the SMS app is performing a query instead of reading directly from openFile, which every other app on my phone seems to do (including other Google apps)

Does anyone know what I need to return here to fullfil the query appropriately? I'm going to go AOSP digging now.


Solution

  • After digging through the source code of the SMS (MMS really) app this is what I came up with.

    Inside UriImage.initFromContentUri the application makes the query code and assumes there are 2 returned columns in the Cursor

     } else {
       filePath = c.getString(c.getColumnIndexOrThrow(Images.Media.DATA));
       mContentType = c.getString(c.getColumnIndexOrThrow(Images.Media.MIME_TYPE));
     }
    

    So inorder for your ContentProvider to work with the MMS app, you need to return a Cursor in query that only has one row and the two columns (Images.Media.DATA & Images.Media.MIME_TYPE) with the appropriate data. The MMS will then make the call to openFile to actually retrieve the image.