Доля намерения Google+ не может получить доступ к изображению

Я вызываю намерение поделиться изображением. это работает с большинством провайдеров, НО с Google+. Google+ открывает активность сообщения без изображения и отображает тост "Вы можете публиковать фотографии, сохраненные на вашем устройстве". в то же время.

    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"));

Я сохраняю изображение с помощью

    Context.openFileOutput(fileName, Context.MODE_WORLD_READABLE);

я понял, что, установив FLAG_GRANT_READ_URI_PERMISSION, я предоставляю конкретный доступ Google+ к этому файлу.

он работает, когда я храню изображение в MediaStore, но на самом деле я не хочу помешать галерее изображений пользователей.

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

любые советы приветствуются

Саймон

Ответы

Ответ 1

Google+ не может получить доступ к file:// Uris из частной папки другого приложения. И FLAG_GRANT_READ_URI_PERMISSION не работает в этом случае, потому что это только для Uris в "данных" части намерения, но не для дополнительных функций.

Общим обходным решением является добавление его в галерею (через MediaStore), но это не обязательно. Правильное решение в этом случае - использовать FileProvider:

FileProvider - это специальный подкласс ContentProvider, который облегчает безопасное совместное использование файлов, связанных с приложением, путем создания content:// Uri для файла вместо file:/// Uri.

Сначала разместите следующее в своем 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>

Затем этот файл в res\xml\filepaths.xml:

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

Затем, чтобы поделиться файлом изображения, убедитесь, что он указан в указанном выше пути (т.е. shared_images в разделе getFilesDir()) и постройте намерение следующим образом:

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

(убедитесь, что полномочия, указанные в методе getUriForFile(), совпадают с тем, который указан в манифесте).

Это создаст content:// Uri (например, content://com.myapp.testshare.fileprovider/shared_images/img1.png, что приложение Google+ сможет получить доступ и, таким образом, включить его в сообщение).

Ответ 2

Саймон

Кажется, что он работает, чтобы установить разрешение после установки uri.

share.putExtra(Intent.EXTRA_STREAM, uri);
share.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

Ответ 3

попробуйте этот, у меня также возникают проблемы с этим, поскольку он появляется в Галерее, если я вставляю.

//здесь присутствует экземпляр файла

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

Ответ 4

Если вы используете пользовательский ContentProvider, вы должны проверить правильность типа MIME изображений. Правильным MIME для jpeg является "image/jpeg". Если вы вернете "image/jpg" в переопределенном getType (Uri uri); затем Google+ не может их прикрепить. Большинство других работ, например. обмена сообщениями и электронной почты. "image/jpg" НЕ является допустимым типом MIME IANA:

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

Спецификация getType ясно об этом, но ее очень легко пропустить (я сделал). Решив это, я хотел, чтобы другие заметили это, потому что это очень неудобно.

Ответ 5

Вы можете использовать это:

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();
    }
}