Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 723
smith324 Avatar asked Aug 24 '11 14:08

smith324


2 Answers

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.

like image 129
smith324 Avatar answered Sep 22 '22 00:09

smith324


An easier way to share a image resource is to save it to external storage (SD-card) and then do:

Uri imageUri = Uri.fromFile(pathToFile);

Update:

Try using

Uri imageUri = Uri.parse("android.resource://com.package.yourapp/" +imageResID);

Update2

Try saving file to Media Store and then sending it:

String url = Media.insertImage(context.getContentResolver(), imageFile.getAbsolutePath(), imageFile.getName(), imageFile.getName());

Uri imageUri = Uri.parse(url);

Final Update using ContentProvider and Cursor:

Your ContentProvider must implement query(..) method and it must return a Cursor. See the source code of UrlImage.initFromContentUri(..) (which is internally used by MMS app) to see how cursor is called. Take a look at the MatrixCursor if it fits the bill.

like image 34
Peter Knego Avatar answered Sep 20 '22 00:09

Peter Knego