Share Intent of Google+ can not access image
Asked Answered
B

5

14

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

Burnie answered 30/3, 2012 at 1:42 Comment(4)
You could always check what permissions the file and folder have, looking into the filesystem using the debug tools in eclipse. Just to make sure that your not suffering from lack of permissions.Carotid
the file permissions look good (-rw-rw-r--). anyways, other apps like the SMS app or Facebook can access and share the image just fine.Burnie
What if you store the image in the cache directory instead, using Context.getCacheDir()?Assuan
nope, that is not better either :-(Burnie
D
6

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).

Descombes answered 2/6, 2014 at 15:54 Comment(5)
Wow, that looks like a nice solution. I cannot really verify this now, but I assume you have done that and it works, so I will mark it as solution. Thanks man, I waited 2 years for this :-)Burnie
I want to share screenshot of UnityGame, from Unity I'm capturing image to "data/data/com.mypackage.name/files/ScreenShot.png". I followed same procedure but I'm getting NullPointerException. Can you share Sample project?Hy
What a great answer. I've tested it and it works perfectly. The only challenge was copying the file to the shared_images folder, which I did with the help of this code: https://mcmap.net/q/203911/-how-to-programmatically-move-copy-and-delete-files-and-directories-on-sdImpetuosity
@Descombes Would you like to post your answer on my similar question here: #27591980 . There is a bounty on it which is due to expire very soon, so be quick if you want to earn that. Cheers.Impetuosity
@ban-geoengineering Glad it helped, I'll try to rewrite it a little bit to better fit your scenario and post it.Descombes
H
2

Simon,

Seems as if it works to set the permission after you set the uri.

share.putExtra(Intent.EXTRA_STREAM, uri);
share.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Homophony answered 1/4, 2012 at 16:42 Comment(1)
I'm using a customized ContentProvider to share the images out of my cache directory. Adding this flag finally allowed me to attach the image in google+, without having to resort to copying the files to the image gallery.Humour
C
1

try this one, I'm also having problems with this as its showing up in Gallery if I do an insert..

//out here is a File instance

String uriString = MediaStore.Images.Media.insertImage(getContentResolver(),
               out.getAbsolutePath(),null,null);   
intent.putExtra(Intent.EXTRA_STREAM,Uri.parse(uriString));

https://github.com/google-plus/google-plus-office-hours/blob/master/2012_08_14-curiosity-android-app/src/com/example/CuriosityActivity.java

Collogue answered 20/8, 2012 at 6:51 Comment(0)
M
1

If you are using a custom ContentProvider you must check that the MIME type of the images is correct. The correct MIME for a jpeg is "image/jpeg". If you return "image/jpg" in the overridden getType(Uri uri); method then Google+ fails to attach them. Most other one work, e.g. messaging and email. "image/jpg" is NOT a valid IANA MIME type:

http://www.iana.org/assignments/media-types/image

The specification of getType is clear about this, but it is very easy to miss (I did). Having solved this, I wanted to ensure others spot this because it is very unobbious.

Makassar answered 25/11, 2013 at 4:5 Comment(0)
K
0

You can use this :

Drawable drawable;
File file;
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) {
    drawable = getResources().getDrawable(imgResId);
} else {
    drawable = getResources().getDrawable(imgResId, null);
}

if (drawable != null) {
    Bitmap bm = ((BitmapDrawable) drawable).getBitmap();

    String path = Environment.getExternalStorageDirectory()
            .toString();
    OutputStream fOut = null;
    file = new File(path, "pic.jpg"); // the File to save to
    try {
        file.createNewFile();
        fOut = new FileOutputStream(file);

        // obtaining the Bitmap
        bm.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
        fOut.flush();
        fOut.close();
        return file;
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
} 
Koonce answered 14/10, 2015 at 23:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.