FileProvider - IllegalArgumentException: Не удалось найти настроенный root

Я пытаюсь сделать снимок с камерой, но я получаю следующую ошибку:

FATAL EXCEPTION: main
Process: com.example.marek.myapplication, PID: 6747
java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Android/data/com.example.marek.myapplication/files/Pictures/JPEG_20170228_175633_470124220.jpg
    at android.support.v4.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.java:711)
    at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:400)
    at com.example.marek.myapplication.MainActivity.dispatchTakePictureIntent(MainActivity.java:56)
    at com.example.marek.myapplication.MainActivity.access$100(MainActivity.java:22)
    at com.example.marek.myapplication.MainActivity$1.onClick(MainActivity.java:35)

AndroidManifest.xml:

<provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="com.example.marek.myapplication.fileprovider"
        android:enabled="true"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />
</provider>

Джава:

Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    // Ensure that there a camera activity to handle the intent
    if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
        // Create the File where the photo should go
        File photoFile = null;
        try {
            photoFile = createImageFile();
        } catch (IOException ex) {
            Toast.makeText(getApplicationContext(), "Error while saving picture.", Toast.LENGTH_LONG).show();
        }
        // Continue only if the File was successfully created
        if (photoFile != null) {
            Uri photoURI = FileProvider.getUriForFile(this,
                    "com.example.marek.myapplication.fileprovider",
                    photoFile);
            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
            startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
        }
    }

file_paths.xml

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

Я искал весь день об этой ошибке и пытался понять FileProvider, но я понятия не имею, что это сообщение об ошибке пытается мне рассказать. Если вы хотите получить дополнительную информацию/код, напишите мне в комментарии.

Ответы

Ответ 1

Ваш файл хранится в getExternalFilesDir(). Это сопоставляется с <external-files-path>, а не <files-path>. Кроме того, ваш путь к файлу не содержит images/ в нем, поэтому атрибут path в вашем XML недопустим.

Замените res/xml/file_paths.xml на:

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

Ответ 2

Аналогичная проблема возникла после активированных ароматов (dev, stage).

До того, как ароматы моего ресурса путей выглядели так:

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path
    name="my_images"
    path="Android/data/pl.myapp/files/Pictures" />
</paths>

После добавления android: authority = "$ {applicationId}.fileprovider" в Manifest appId был pl.myapp.dev или pl.myapp.stage зависит от вкуса, и приложение начало сбой. Я удалил полный путь и заменил его точкой, и все начало работать.

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path
        name="my_images"
        path="." />
</paths>

Ответ 3

Это может решить любую проблему: все теги добавляются, поэтому вам не нужно беспокоиться о пути к папкам. Замените res/xml/file_paths.xml следующим образом:

<?xml version="1.0" encoding="utf-8"?>
<paths>
  <external-path
    name="external"
    path="." />
  <external-files-path
    name="external_files"
    path="." />
  <cache-path
    name="cache"
    path="." />
  <external-cache-path
    name="external_cache"
    path="." />
<files-path
    name="files"
    path="." />
</paths>

Ответ 4

Если вы используете внутренний кеш, используйте его.

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <cache-path name="cache" path="/" />
</paths>

Ответ 5

Это тоже смущает меня.

Проблема заключается в атрибуте "path" в вашем XML файле.

Из этого документа FileProvider 'path' - это подкаталог, но в другом документе (камера/фотобаза) "путь" - полный путь.

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="my_images" path="Android/data/com.example.package.name/files/Pictures" />
</paths>

Я просто изменяю этот "путь" на полный путь, и он просто работает.

Ответ 6

Проверьте, сколько хранилищ вашего устройства предлагает - совместное использование файлов из вторичного хранилища не поддерживается. Посмотрите на источник FileProvider.java (из поддержки-core-utils 25.3.1):

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

Таким образом, они берут только первое хранилище.

Кроме того, вы можете видеть, что getExternalCacheDirs() используется для получения списка хранилищ через интерфейс ContextCompat. См. документация в своих пределах (он сказал, чтобы не распознавать USB-вспышки, например). Лучше всего сделать отладочный вывод списка хранилищ из этого API самостоятельно, чтобы вы могли проверить, что путь к хранилищу соответствует пути, переданному в getUriForFile().

Там уже отправлен билет (в соответствии с 06-2017) в трекер Google, запрашивая поддержку нескольких хранилищ. В конце концов, я нашел SO вопрос по этому вопросу.

Ответ 7

Я бы опоздал, но нашел решение для него. Работая отлично, я просто изменил файл XML пути:

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

Ответ 8

Имейте в виду, что внешний путь не указывает на ваше вторичное хранилище, а также "съемное хранилище" (несмотря на название "внешний"). Если вы получаете "Не удалось найти настроенный root", вы можете добавить эту строку в свой XML файл.

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

Подробнее см. Здесь FileProvider и дополнительное внешнее хранилище

Ответ 9

Ничто из этого не сработало для меня. Единственный подход, который работает, заключается не в том, чтобы объявить явный путь в xml. Так сделайте это и будьте счастливы:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="my_images" path="." />
</paths>

Здесь также есть отличный учебник по этому вопросу: https://www.youtube.com/watch?v=9ZxRTKvtfnY&t=613s

Ответ 10

Я уверен, что я опоздал на вечеринку, но ниже работал для меня.

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

Ответ 11

Моя проблема заключалась в том, что у меня были перекрывающиеся имена в пути к файлам для разных типов, например:

<cache-path
    name="cached_files"
    path="." />
<external-cache-path
    name="cached_files"
    path="." />

После того, как я изменил имена ("cached_files"), чтобы быть уникальными, я избавился от этой ошибки. Я предполагаю, что эти пути хранятся в некоторых HashMap или что-то, что не позволяет дублировать.

Ответ 12

Потерял 2 недели, пытаясь найти решение... Если вы прибываете сюда после того, как попробуйте что-нибудь выше:

1 - Убедитесь, что ваш поставщик тегов находится внутри приложения тегов

<application>

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

</application>

2 - Если вы безуспешно пробуете много путей, попробуйте следующее:

<?xml version="1.0" encoding="utf-8"?>
<paths>
  <cache-path name="cache" path="." />
  <external-path name="external" path="." />

  <root-path name="root" path="." />
  <files-path name="my_images" path="/" />
  <files-path name="my_images" path="myfile/"/>
  <files-path name="files" path="." />

  <external-path name="external_files" path="." />
  <external-path name="images" path="Pictures" />
  <external-path name="my_images" path="." />
  <external-path name="my_images" path="Android/data/com.companyname.yourproject/files/Pictures" />
  <external-path name="my_images" path="Android/data/com.companyname.yourproject/files/Pictures/" />

  <external-files-path name="images" path="Pictures"/>
  <external-files-path name="camera_image" path="Pictures/"/>
  <external-files-path name="external_files" path="." />
  <external-files-path name="my_images" path="my_images" />

  <external-cache-path name="external_cache" path="." />

</paths>

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

3 - Не забудьте проверить, активирована ли камера в вашем эмуляторе.

Ответ 13

Это работало и для меня. Вместо того, чтобы давать полный путь, я дал путь = "Картинки", и он отлично работал.

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

Ответ 14

Что я сделал для этого -

AndroidManifest.xml

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

filepaths.xml(разрешить FileProvider обмениваться всеми файлами, находящимися в каталоге внешних файлов приложения)

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-files-path name="files"
        path="/" />
</paths>

и в классе java -

Uri fileProvider = FileProvider.getUriForFile(getContext(),"com.mydomain.fileprovider",newFile);

Ответ 15

ни один из вышеперечисленных не работал для меня, после нескольких часов отладки я узнал, что проблема в createImageFile(), в частности absolute path и relative path

Я предполагаю, что вы, ребята, используете официальное руководство по Android для фотосъемки. https://developer.android.com/training/camera/photobasics

    private static File createImageFile(Context context) throws IOException {
        // Create an image file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String imageFileName = "JPEG_" + timeStamp + "_";
        File storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        File image = File.createTempFile(
                imageFileName,  /* prefix */
                ".jpg",         /* suffix */
                storageDir      /* directory */
        );

        // Save a file: path for use with ACTION_VIEW intents
        mCurrentPhotoPath = image.getAbsolutePath();
        return image;
    }

Обратите внимание на storageDir, это место, где будет создан файл. Поэтому, чтобы получить абсолютный путь к этому файлу, я просто использую image.getAbsolutePath(), этот путь будет использоваться в onActivityResult если вам нужно изображение растрового изображения после съемки

ниже file_path.xml, просто используйте . так что он использует абсолютный путь

<paths>
    <external-path
        name="my_images"
        path="." />
</paths>

и если вам нужно растровое изображение после съемки

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        Bitmap bmp = null;
        try {
            bmp = BitmapFactory.decodeFile(mCurrentPhotoPath);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

Ответ 16

Я потратил 5 часов на это..

Я перепробовал все методы, описанные выше, но это зависит от того, какое хранилище использует ваше приложение.

https://developer.android.com/reference/android/support/v4/content/FileProvider#GetUri

Проверьте документацию, прежде чем пытаться коды.

В моем случае, так как files-path будет Context.getFilesDir(). Самое Context.getFilesDir() что Context.getFilesDir() друг на друга.

что я ищу это

data/user/0/com.psh.mTest/app_imageDir/20181202101432629.png

Context.getFilesDir()

возвращает /data/user/0/com.psh.mTest/files

поэтому тег должен быть

.... files-path name="app_imageDir" path="../app_imageDir/"......

Тогда это работает!

Ответ 17

Я получаю эту ошибку Failed to find configured root that contains...

Следующая работа решает мою проблему

Рез /XML/file_paths.xml

<paths xmlns:android="http://schemas.android.com/apk/res/android">
        <external-path name="media" path="." />
</paths>

AndroidManifest.xml

<provider
      android:name="android.support.v4.content.FileProvider"
      android:authorities="[PACKAGE_NAME]"
      android:exported="false"
      android:grantUriPermissions="true">
         <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths">
         </meta-data>
</provider>

ActivityClass.java

void shareImage() {
        Intent intent = new Intent(Intent.ACTION_SEND);
        intent.setType("image/*");
        intent.putExtra(Intent.EXTRA_STREAM, FileProvider.getUriForFile(this,"com.slappstudio.pencilsketchphotomaker", selectedFilePath));
        startActivity(Intent.createChooser(intent,getString(R.string.string_share_with)));
    }

Ответ 18

Официальный документ Android говорит, что file_paths.xml должен иметь:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">   
    <external-path name="my_images"    
        path="Android/data/com.example.package.name/files/Pictures" />
</paths>

Но чтобы заставить его работать в последнем андроиде, в конце пути должно быть "/", например:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">   
    <external-path name="my_images"    
        path="Android/data/com.example.package.name/files/Pictures/" />
</paths>

Ответ 19

Следующее изменение файла xml file_paths сработало для меня.

 <external-files-path name="my_images" path="Pictures"/>
 <external-files-path name="my_movies" path="Movies"/>

Ответ 20

Я наконец нашел свою проблему. Я описал это в этой ссылке.

моя проблема заключалась в различии между идентификатором приложения в режиме отладки и выпуска

Ответ 21

Это зависит от того, какое хранилище вы хотите делать, ВНУТРЕННЕЕ или ВНЕШНЕЕ

для ВНЕШНЕГО ХРАНЕНИЯ

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

но для ВНУТРЕННЕГО ХРАНЕНИЯ, будьте осторожны с этим путем, потому что он использует метод getFilesDir(), который означает, что ваш файл будет находиться в корневом каталоге приложения ("/")

  File storeDir = getFilesDir(); // path "/"

Таким образом, ваш файл поставщика должен выглядеть следующим образом:

<paths>
    <files-path name="my_images" path="/" />
</paths>

Ответ 22

Я вижу, что по крайней мере вы не предоставляете тот же путь, что и другие, в file_paths.xml. Поэтому, пожалуйста, убедитесь, что вы указали то же самое имя или путь пакета в трех местах, включая:

  • android:authorities атрибут в манифесте
  • path атрибут в file_paths.xml
  • authority при вызове FileProvider.getUriForFile().

Ответ 23

  • Для пользователей Xamarin.Android

Это также может быть результатом не обновления пакетов поддержки при настройке Android 7.1, 8.0+. Обновите их до v25.4.0.2 +, и эта конкретная ошибка может исчезнуть (если вы правильно настроили файл file_path, как утверждают другие).


Предоставление контекста: я переключился на таргетинг Oreo из Нуга в приложение Xamarin.Forms и сделайте снимок с Xam.Plugin.Mediaначалось сбой с указанным выше сообщением об ошибке, поэтому обновление пакетов помогло нормально.

Ответ 24

Я заметил, что политика или поведение файла path.xml изменилось между библиотекой поддержки 26 и 27. Для захвата изображения с камеры я увидел следующие изменения:

  • С 26 я должен был использовать <external-path> и полный путь, указанный в аргументе path.

  • С 27 я должен был использовать <external-files-path> и только подпапку в аргументе path.

Итак, что конкретно работало для меня в Support Library 27, поскольку файл path.xml был

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

Ответ 25

У меня была та же проблема, я попробовал приведенный ниже код для его работы.

1.Создать Xmlfile: provider_paths

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

2. Файл Mainfest

 <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.ril.learnet.provider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths"/>
 </provider>

3.В файле Java.

      File file =  new File(getActivity().getFilesDir(), "myfile");
        if (!file.exists()) {
            file.mkdirs();
        }
        String  destPath = file.getPath() + File.separator + attachmentsListBean.getFileName();

               file mfile = new File(destPath);
                Uri path;
                Intent intent = new Intent(Intent.ACTION_VIEW);
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
                {
                    path = FileProvider.getUriForFile(AppController.getInstance().getApplicationContext(), AppController.getInstance().getApplicationContext().getPackageName() + ".provider", mfile );
                    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                } else {
                    path = Uri.fromFile(mfile);
                }
   intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    intent.setDataAndType(path, "image/*");
                    getActivity().startActivity(intent);

Ответ 26

Привет друзья Попробуйте это

В этом кодексе

1) Как объявить 2 поставщика файлов в манифесте.

2) Первый провайдер для загрузки файла

3) второй провайдер, используемый для камеры и галерей

ШАГ 1

     <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="${applicationId}.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_paths" />
    </provider>

Provider_paths.xml

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

Второй провайдер

     <provider
        android:name=".Utils.MyFileProvider"
        android:authorities="${applicationId}.provider"
        android:exported="false"
        android:grantUriPermissions="true"
        tools:replace="android:authorities"
        tools:ignore="InnerclassSeparator">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_path" />
    </provider>

file_path.xml

<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="storage/emulated/0" path="."/>
</paths>

.Utils.MyFileProvider

Создать класс MyFileProvider (только создать класс, который не объявляет какой-либо метод)

Когда вы использовали File Provider used (.fileprovider), это имя использовалось для изображения (.provider).

ЕСЛИ какая-либо проблема. Чтобы понять этот код, вы можете связаться по адресу [email protected] Я помогу вам.

Ответ 27

Если ничего не помогает, и вы получаете ошибку

failed to find configured root that contains /data/data/...

затем попробуйте изменить некоторую строку, например:

File directory = thisActivity.getDir("images", Context.MODE_PRIVATE);

чтобы:

File directory = new File(thisActivity.getFilesDir(), "images");

и в файле xml:

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

что странно, поскольку папка, к которой я обращаюсь, - это /images.

Ответ 28

Проблема может быть не только в пути XML.

Следующее - мое исправление:

Просмотр корневого курса в android.support.v4.content.FileProvider$SimplePathStrategy.getUriForFile():

    public File getFileForUri(Uri uri) {
        String path = uri.getEncodedPath();

        final int splitIndex = path.indexOf('/', 1);
        final String tag = Uri.decode(path.substring(1, splitIndex));
        path = Uri.decode(path.substring(splitIndex + 1));

        final File root = mRoots.get(tag); // mRoots is parsed from path xml
        if (root == null) {
            throw new IllegalArgumentException("Unable to find configured root for " + uri);
        }

        // ...
    }

Это означает, что mRoots должен содержать тег запрошенного URI. Поэтому я пишу код для печати mRoots и тега mRoots, а затем легко найти теги не совпадают.

Получается, что установка полномочий провайдера как ${applicationID}.provider - глупая идея ! Эти полномочия настолько распространены, что могут быть использованы другими провайдерами, что испортит конфигурацию пути!

Ответ 29

Вам нужно изменить файл xml file_paths.xml из

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

в

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <fexeternal-path name="my_images" path="Android/data/com.example.marek.myapplication/files/Pictures"/>
</paths>

Ответ 30

Моя проблема была file_paths.xml Имя файла: я file_paths.xml в res/xml, в то время как для ресурса был задан файл provider_paths.xml в манифесте:

<provider
        android:authorities="ir.aghigh.radio.fileprovider"
        android:name="android.support.v4.content.FileProvider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_paths"/>
    </provider>

Я изменил provider_paths на file_paths и проблема решена.