Совместное использование видео + текста с FileProvider вызывает исключение отказа в разрешении

у меня есть отказ в доступе при совместном использовании видеофайла .mp4 с поставщиком файлов и Intent.EXTRA_TEXT .

если я удалю строку:

shareIntent.putExtra(Intent.EXTRA_TEXT, "#myappHashtag");

все работает. Но мне нужны оба видеофайла + дополнительный текст.

Я думаю, проблема в следующем: caption=%23myappHashtag в URI общего ресурса, но как я могу это исправить?

Большое спасибо.

private void ShareItem(File fileToShare) {

    String package_name = "com.lucagrillo.myapp";
    Uri uri = FileProvider.getUriForFile(this, package_name + ".fileprovider", fileToShare);
    Intent shareIntent = new Intent();
    shareIntent.setAction(Intent.ACTION_SEND);
    shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
    shareIntent.putExtra(Intent.EXTRA_TEXT, "#myappHashtag");
    shareIntent.setType(intentFormatType);

    startActivity(Intent.createChooser(shareIntent, getResources().getText(R.string.share_with)));

}

Исключение:

Writing exception to parcel
    java.lang.SecurityException: Permission Denial: reading android.support.v4.content.FileProvider uri content://com.lucagrillo.myapp.fileprovider/images/shareFile.mp4?caption=%23myappHashtag from pid=9630, uid=10093 requires the provider be exported, or grantUriPermission()
    at android.content.ContentProvider.enforceReadPermissionInner(ContentProvider.java:608)
    at android.content.ContentProvider$Transport.enforceReadPermission(ContentProvider.java:483)
    at android.content.ContentProvider$Transport.enforceFilePermission(ContentProvider.java:474)
    at android.content.ContentProvider$Transport.openTypedAssetFile(ContentProvider.java:419)
    at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:313)
    at android.os.Binder.execTransact(Binder.java:565)

Поставщик файла манифеста:

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

person L.Grillo    schedule 29.08.2016    source источник
comment
На какой версии Android вы тестируете? Можете ли вы также включить запись манифеста для FileProvider?   -  person ianhanniballake    schedule 29.08.2016
comment
я тестирую на андроиде 7.0. Только что заметил, что он работает со многими приложениями, кроме WhatsApp.   -  person L.Grillo    schedule 29.08.2016
comment
Добавлен поставщик файла манифеста   -  person L.Grillo    schedule 29.08.2016
comment
Совместно используемый URI заканчивается на shareFile.mp4?caption=%23myappHashtag — это действительно имя вашего файла? Что произойдет, если вы удалите часть подписи?   -  person ianhanniballake    schedule 29.08.2016
comment
удаление shareIntent.putExtra(Intent.EXTRA_TEXT... результат uri без ?caption=%23myappHashtag и все идет нормально   -  person L.Grillo    schedule 30.08.2016
comment
Сумасшествие в том, что при публикации в Whatsapp он работает с файлами .jpg, а НЕ с .mp4. Я думаю, что это проблема WhatsApp.   -  person L.Grillo    schedule 30.08.2016


Ответы (1)


Вы пропустили вызов addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) на своем Intent. Это будет работать, если ваш minSdkVersion 21 или выше, чтобы предоставить права на этот Uri любому приложению, обрабатывающему запрос ACTION_SEND.

Если ваш minSdkVersion ниже 21, вам придется предоставить права всем возможным обработчикам ACTION_SEND для вашего Intent. На этих старых устройствах addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) предоставляет разрешение только на Uri, которое у вас было бы в аспекте «данные» Intent (например, new Intent(Intent.ACTION_VIEW, uri)), а не на Uri в дополнительных значениях.

Вы получаете код, который выглядит примерно так:

  if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP) {
    i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
  }
  else {
    List<ResolveInfo> resInfoList=
      getPackageManager()
        .queryIntentActivities(i, PackageManager.MATCH_DEFAULT_ONLY);

    for (ResolveInfo resolveInfo : resInfoList) {
      String packageName = resolveInfo.activityInfo.packageName;
      grantUriPermission(packageName, outputUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
    }
  }

(где i — это Intent, а outputUri — это Uri, которые вы добавили дополнительно)

Также напомню: реализации ACTION_SEND не обязаны поддерживать и EXTRA_TEXT, и EXTRA_STREAM.

person CommonsWare    schedule 29.08.2016
comment
Фактически, Android с Jelly Bean автоматически переносит ваш поток и добавляет FLAG_GRANT_READ_URI_PERMISSION к любому намерению ACTION_SEND. - person ianhanniballake; 29.08.2016
comment
@ianhanniballake: В этом нет особого смысла. addFlags() не влияет на Uri дополнительные функции до версии Android 5.0. Это связано с setClipData() в коде, на который вы ссылаетесь? - person CommonsWare; 29.08.2016
comment
как видно из связанного кода, метод migrateExtraStreamToClipData преобразует дополнительные данные в ClipData, а затем добавляет флаг предоставления - person ianhanniballake; 29.08.2016
comment
@ianhanniballake: Вы говорите, что помещение Uri в ClipData, а затем добавление флага означает, что Uri можно прочитать, даже если получатель не использует сам ClipData (например, получает Uri из EXTRA_STREAM)? Если да, то это хорошая техника, которую нужно знать, и я могу вспомнить по крайней мере один мой книжный пример, который мне нужно обновить. - person CommonsWare; 29.08.2016
comment
доступ к URI и то, как вы читаете его из Intent, — это две независимые вещи. Очевидно, что это работает только с API 16+, но если это ваша версия minSdkVersion, все немного проще. - person ianhanniballake; 29.08.2016
comment
@ianhanniballake: доступ к URI и то, как вы его читаете из намерения, - это две независимые вещи - понятно. Однако идея использовать setClipData() исключительно для побочного эффекта разрешения не приходила мне в голову, поэтому я хотел убедиться, что понимаю ситуацию. Большое спасибо! - person CommonsWare; 29.08.2016