5

Как я могу обслуживать файлы из внешнего хранилища SECONDARY с помощью 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, что соответствует вторичному внешнему пути хранения. ..

+0

Что вы имеете в виду со вторичным внешним хранилищем? – greenapps

+0

Каталоги, возвращаемые 'ContextCompat.getExternalFilesDirs' с индексом массива> 0. На большинстве устройств это, вероятно, съемная SD-карта. – artkoenig

+0

AFAIK, 'FileProvider' не поддерживает это. Вы могли бы пристроить что-то с помощью [моего «StreamProvider»] (https://github.com/commonsguy/cwac-provider), хотя поддержка этого «из коробки» не поддерживается. Я добавил это в список дел для «StreamProvider», так как вы делаете хороший вывод. В частности, поскольку в этих местах не задействованы разрешения приложений, они должны быть обслуживаемыми, по крайней мере, когда они существуют. То, что может показаться сложным, - это правильно обрабатывать случай, когда съемное хранилище недоступно, но вы просили его обслуживать. – CommonsWare

ответ

4

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

Я выпустил bug report.

1

Как временное решение вы можете использовать абсолютные трактов:

<!-- 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" /> 
+1

С новыми устройствами внешний путь зависит от вставленной SD-карты, так как он использует ссылочный идентификатор, поэтому невозможно использовать абсолютный путь. – 3c71

1

Так что я в конечном итоге делает следующее:

Пытаться создать Ури через FileProvider, если это не удается из-за:

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

Я просто создаю очередной Ури.

Вот мой код:

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

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

Weird Google ... очень странно.

+1

сбоев в 7.0+ –

2

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

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

</paths> 
2

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

Код от поддержки: поддержка-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)) { 

Однако, существует специальный TAG в FileProvider: корневой путь, который не рассматривается в официальной ссылке.

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

Итак, корень пути соответствует всем путям.

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

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

Обратите внимание, что это может привести к утечке структуры вашего каталога.

Смежные вопросы