FileProvider и вторичное внешнее хранилище

Как я могу обслуживать файлы из ВТОРИЧНОГО внешнего хранилища, используя FileProvider?

Текущая реализация FileProvider обрабатывает только первый каталог, возвращаемый ContextCompat.getExternalFilesDirs.

...    
} else if (TAG_EXTERNAL_FILES.equals(tag)) {
   File[] externalFilesDirs = ContextCompat.getExternalFilesDirs(context, null);
   if (externalFilesDirs.length > 0) {
       target = externalFilesDirs[0];
   }
}
...

Кажется, нет способа определить запись <path> для FileProvider, которая соответствует вторичному пути внешнего хранилища...


person artkoenig    schedule 29.10.2016    source источник
comment
Что вы имеете в виду под вторичным внешним хранилищем?   -  person greenapps    schedule 29.10.2016
comment
Каталоги, возвращаемые ContextCompat.getExternalFilesDirs с индексом массива › 0. На большинстве устройств это, вероятно, будет съемная SD-карта.   -  person artkoenig    schedule 29.10.2016
comment
Насколько я знаю, FileProvider не поддерживает это. Вы можете настроить что-то с помощью my StreamProvider, хотя это не поддерживается из коробки. . Я добавил это в свой список дел на StreamProvider, так как вы правильно заметили. В частности, поскольку для этих местоположений не используются разрешения приложений, они должны быть доступны для обслуживания, по крайней мере, когда они существуют. Что может оказаться сложным, так это правильная обработка случая, когда съемное хранилище недоступно, но вы запросили его обслуживание.   -  person CommonsWare    schedule 29.10.2016


Ответы (5)


И ответ... FileProvider не поддерживает это. В Android 7 это еще более серьезная проблема из-за устаревания схемы file:// Uri.

Я отправил отчет об ошибке.

person artkoenig    schedule 20.11.2016
comment
Спасибо за отчет об ошибке и ссылку, другой разработчик предоставляет рабочий подкласс FileProvider. - person Tim Autin; 18.11.2019

FileProvider не поддерживает вторичное хранилище из-за приведенного ниже кода:

Код от support:support-core-utils:26.1.0 FileProvider

            } else if (TAG_EXTERNAL_FILES.equals(tag)) {
                File[] externalFilesDirs = ContextCompat.getExternalFilesDirs(context, null);
                if (externalFilesDirs.length > 0) {
                    target = externalFilesDirs[0];// Code here, That's why!!!
                }
            } else if (TAG_EXTERNAL_CACHE.equals(tag)) {

Однако в FileProvider есть специальный TAG: root-path, который не описан в официальных справочниках.

            if (TAG_ROOT_PATH.equals(tag)) {
                target = DEVICE_ROOT;// DEVICE_ROOT = new File("/");
            } else if (TAG_FILES_PATH.equals(tag)) {

Итак, root-path соответствует всем путям.

Просто введите этот код в XML-файл FileProvider, после чего FileProvider сможет обрабатывать файл во вторичном хранилище.

<root-path name="root" path="." />

Имейте в виду, это может привести к утечке вашей структуры каталогов.

person Shaw    schedule 25.12.2017

Чтобы обрабатывать файлы, расположенные на внешних SD-картах, я изменил свой provider_paths.xml на

<paths>
    <external-path path="." name="external_files" />
    <root-path path="." name="sdcard1" />

</paths>
person Simon    schedule 17.07.2017

В качестве обходного пути вы можете использовать абсолютные пути:

<!-- secondary external storage with path /storage/extSdCard -->
<root-path path="/storage/extSdCard/Android/data/YOUR_PACKAGE/files/" name="extSdCard" />

<!-- secondary external storage with path /storage/sdcard1  -->
<root-path path="/storage/sdcard1/Android/data/YOUR_PACKAGE/files/" name="sdcard1" />
person danik    schedule 31.05.2017
comment
На более новых устройствах внешний путь зависит от вставленной SD-карты, поскольку она использует ссылочный идентификатор, поэтому невозможно использовать абсолютный путь. - person 3c71; 01.11.2017

В итоге я сделал следующее:

Попробуйте создать Uri через FileProvider, если это не удается из-за:

java.lang.IllegalArgumentException: Failed to find configured root that contains

Я просто создаю обычный Uri.

Вот мой код:

try {
        uri = FileProvider.getUriForFile(context,
                MY_AUTHORITY_STRING,
                imageFile);
    } catch (Exception e) {
        CLog.d(TAG, e);
        uri = Uri.fromFile(imageFile);
    }

Я не знаю почему, но он работает, FileProvider не может получить доступ к файлу (поскольку он находится во вторичном внешнем хранилище), а затем uri успешно создается в предложении catch.

Странный Google... очень странный.

person Udi Oshi    schedule 09.07.2017
comment
вылетает в 7.0+ - person farhan patel; 10.10.2017