Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Share Intent of Google+ can not access image

i am calling an intent to share an image. this works with most providers, BUT with Google+. Google+ opens the post activity without the image and displays the toast "You can only post photos stored on your device." at the same time.

    File f = storeImage(image); // f = /data/data/com.myapp/files/1333070776978.jpg
    Uri uri = Uri.fromFile(f);

    Intent share = new Intent(Intent.ACTION_SEND);
    share.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 
    share.setType("image/jpeg");
    share.putExtra(Intent.EXTRA_STREAM, uri);
    share.putExtra(Intent.EXTRA_TITLE,"Share that title");
    share.putExtra(Intent.EXTRA_SUBJECT,"Share that subject");
    share.putExtra(Intent.EXTRA_TEXT,"Check that out...");
    share.putExtra("sms_body", "sms body");
    startActivity(Intent.createChooser(share, "Share Image"));

i save the image with

    Context.openFileOutput(fileName, Context.MODE_WORLD_READABLE);

my understanding was that by setting FLAG_GRANT_READ_URI_PERMISSION, i give Google+ specific access to this file.

it works when i store the image into the MediaStore, but i actually don't wanna clutter the users image gallery.

    ContentValues values = new ContentValues(2);
    values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
    values.put(MediaStore.Images.Media.DATA, f.getAbsolutePath());
    Uri uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);

any advice is appreciated

Simon

like image 216
SimonSays Avatar asked Mar 30 '12 01:03

SimonSays


1 Answers

Google+ cannot access file:// Uris from the private folder of another application. And the FLAG_GRANT_READ_URI_PERMISSION doesn't work in this case because it's only for Uris in the "data" part of an Intent, but not for extras.

One common workaround is to add it to the gallery (via the MediaStore) but it's not necessary to do so. The correct solution in this case is to use a FileProvider:

FileProvider is a special subclass of ContentProvider that facilitates secure sharing of files associated with an app by creating a content:// Uri for a file instead of a file:/// Uri.

First place the following in your AndroidManifest.xml

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="com.myapp.testshare.fileprovider"
    android:grantUriPermissions="true"
    android:exported="false">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/filepaths" />
</provider>

Then this file in res\xml\filepaths.xml:

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <files-path name="shared_images" path="shared_images/" />
</paths>

Then, to share an image file, make sure it's in the path specified above (i.e. shared_images under getFilesDir()) and build the intent as follows:

File file = getImageFileToShare();
Uri fileUri = FileProvider.getUriForFile(this, "com.myapp.testshare.fileprovider", file);

Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_STREAM, fileUri);
intent.setType("image/png");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

startActivity(intent);

(Make sure the authority specified in the getUriForFile() method matches the one in the manifest).

This will produce a content:// Uri (like content://com.myapp.testshare.fileprovider/shared_images/img1.png that the Google+ app will be able to access, and thus include in the post).

like image 60
matiash Avatar answered Sep 24 '22 00:09

matiash