Выбор файла изображения из галереи с помощью FileProvider
Компиляция для Android N Я столкнулся с проблемой FileProvider
. Мне нужно, чтобы пользователь мог выбрать изображение из галереи/сделать снимок с помощью камеры, а затем обрезать его до квадрата.
Мне удалось реализовать FileProvider
для съемки с камерой, но у меня есть серьезная проблема с выбором изображения из галереи. Проблема в том, что в галерее есть много файлов из разных мест, и у меня есть Exception, например:
java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/6133-3766/DCIM/100ANDRO/DSC_0035.JPG
Итак, вопрос в том, что я могу поместить в file_paths.xml, чтобы получить доступ в любом месте /storage/
. Я не могу полагаться на точный путь, поскольку, возможно, изображения из WhatsApp и подобных приложений, например, изображение WhatsApp получает этот путь:
/storage/emulated/0/WhatsApp/Media/WhatsApp Images/IMG-20160821-WA0000.jpg
который мне удалось решить пустым путем:
<external-path name="external_storage" path=""/>
который похож на Environment.getExternalStorageDirectory()
в соответствии с документацией .
Но до сих пор не удается понять, как обращаться с изображениями, хранящимися в /storage/SOME_DIR/
. Пожалуйста, помогите.
Ответы
Ответ 1
Я думаю, что этот вопрос основан на недоразумении.
Цель FileProvider - предоставить доступ (внешнему приложению) к файлу, который уже контролирует ваше приложение.
Вам никогда не удастся использовать собственный поставщик файлов, чтобы получить доступ к файлу, принадлежащему внешнему приложению.
Это зависит от внешнего приложения, которое предоставит вам доступ с помощью поставщика файлов, если он захочет.
Кажется, это вопрос, о котором идет речь. Если я не понял ваш вопрос, дайте мне знать, но если я пойму это, то, что вы пытаетесь сделать, просто не сработает.
Ответ 2
Согласовано с @x-code, вы не очень хорошо разбираетесь в проблеме, хотя, если вы пытаетесь получить доступ к внутренним данным другого приложения, тогда у вас должны быть разрешения на это.
Файлы, которые по праву принадлежат вашему приложению, и должны быть удалены, когда пользователь удалит ваше приложение. Хотя эти файлы технически доступны пользователю и другим приложениям, поскольку они находятся на внешнем хранилище, это файлы, которые реально не предоставляют ценность пользователю вне вашего приложения.
Собственно, я нашел в документации, что версия SDK 24 теперь обновлена многими схемами и имеет значительные изменения в работе с файлами, из документации проблема с файлом:// описывается как..
Передача файла://URI вне домена пакета могут оставить приемник с недостижимым путем. Поэтому попытки передать файл://URI запускают FileUriExposedException. Рекомендуемым способом совместного использования содержимого частного файла является использование FileProvider.
Из-за соображений безопасности настоятельно рекомендуется использовать Content://вместо использования файла://поэтому в основном используйте ContentProvider вместо FileProvider.
Простой пример его использования ниже,
in AndroidMenifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
...
<application
...
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
</application>
</manifest>
И затем создайте файл поставщика _paths.xml
в папке xml в папке res
. Папка может понадобиться для создания, если она не существует.
Содержимое файла показано ниже. В нем описано, что мы хотели бы предоставить доступ к внешнему хранилищу в корневой папке (path=".")
с именем external_files
.
Рез /XML/provider _paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>
теперь использовать его,
Uri photoURI = FileProvider.getUriForFile(MainActivity.this,
BuildConfig.APPLICATION_ID + ".provider",
createImageFile());
Я взял это из этого блога, поэтому, пожалуйста, прочитайте его для полного понимания. Надеюсь, это поможет всем.