My app generates images that a user can save or share with others. The code below works for most apps: Messenger, Facebook, Dropbox, email, etc. Meaning, the image is loaded by the chosen app, and a user can share the image successfully with that app.
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("image/png");
File o = new File(dir, "file.png");
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(o));
startActivity(Intent.createChooser(intent , "Send options"));
However, when I choose Google+ in the list of apps, google+ starts, but the image is not included in the post window. Instead, google+ displays a Toast message with:
"You can only post photos stored on your device."
This is a little confusing, because the image is on the external SD card, i.e. /mnt/sdcard/AppDir/file.png. I am using the latest update of Google+ app (2.3.1.242969).
Is there another trick to sharing an image with google+?
Thank you.
UPDATE:
My app generates the images that are shared, so the sample below from @chirag-shah wasn't directly applicable. But, using the MediaStore looks like the right idea. I've settled on the basic code below:
void shareImage(int position) {
File f = getFileFor(position);
ContentValues values = new ContentValues(2);
values.put(MediaStore.Images.Media.MIME_TYPE, "image/png");
values.put(MediaStore.Images.Media.DATA, f.getAbsolutePath());
Uri uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("image/png");
intent.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(Intent.createChooser(intent , "Send options"));
}
This works with Google+ and all other apps I've tested with. I'm leaving the question open in case this is not best practice. Can anyone confirm that this is the right way to do it?
Great catch! You can specify the MediaStore Uri (which looks like content://media/external/images/media/42) instead of the absolute path on the file system.
Example:
public class MyActivity extends Activity {
...
static final int IMAGE_REQUEST = 0;
protected void pickImage() {
Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, IMAGE_REQUEST);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == IMAGE_REQUEST) {
Uri uri = data.getData();
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("image/png");
// uri looks like content://media/external/images/media/42
intent.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(Intent.createChooser(intent , "Share"));
}
}
}
Thanks for raising this question!
Yes it seems that Google+ only accepts media from content providers (content:// uris), not file:// uris. So we need to put the image into MediaStore first. An easier way to do this is:
MediaStore.Images.Media.insertImage(context.getContentResolver(), tmpFile.getAbsolutePath(), tmpFile.getName(), null);
The reason why you are getting this error is because of "on the sd card" is NOT "on your device".
A discussion about this issue can be found here: https://groups.google.com/a/googleproductforums.com/forum/#!topic/google-plus-discuss/pdlOTM8JEXg/discussion
The workaround via the MediaStore seems to be the only solution until Google updates the Google+ app with a fix.
Update: The solution mentioned above only works if you want to share an image a single time. If you call ContentResolver.insert(...) multiple times, you will end up with the image showing up multiple times in your gallery. I came up with the following solution that tries to get the existing id of the image and if it doesn't exist, you can insert it...
Cursor c = getActivity().getContentResolver()
.query(Images.Media.EXTERNAL_CONTENT_URI,
null,
Images.Media.DATA + "=?",
new String[] { filePath }, null);
if (c.getCount() > 0 && c.moveToFirst()) {
Uri shareUri = Uri.withAppendedPath(
Images.Media.EXTERNAL_CONTENT_URI,
""
+ c.getInt(c
.getColumnIndex(Images.Media._ID)));
c.close();
startActivity(Intent.createChooser(
new Intent(Intent.ACTION_SEND)
.putExtra(Intent.EXTRA_STREAM,
shareUri).setType(
"image/*"), ""));
} else {
// ContentResolver.insert(...) and use that uri...
}