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
и проблема решена.