web-dev-qa-db-fra.com

FileProvider - IllegalArgumentException: Impossible de trouver la racine configurée

J'essaie de prendre une photo avec l'appareil photo, mais l'erreur suivante s'affiche:

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>

Java:

Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    // Ensure that there's 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);
        }
    }

chemin_fichiers.xml

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

Je cherchais cette erreur toute la journée et essayais de comprendre FileProvider, mais je n'ai aucune idée de ce que ce message d'erreur tente de me dire. Si vous voulez plus d'informations/code, écrivez-moi dans le commentaire.

105
Pivoman

Votre fichier est stocké sous getExternalFilesDir(). Cela correspond à <external-files-path>, pas <files-path>. De plus, votre chemin de fichier ne contient pas images/, donc l'attribut path dans votre XML n'est pas valide.

Remplacez res/xml/file_paths.xml par:

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

Vous avez un problème similaire après avoir activé les saveurs (dev, stage).

Avant les saveurs, ma ressource de chemin ressemblait à ceci: 

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

Après avoir ajouté Android: autorités = "$ {applicationId} .fileprovider" Dans Manifest appId était pl.myapp.dev ou pl.myapp.stage dépend de la saveur et de l'application a commencé à planter. J'ai retiré le chemin complet et l'ai remplacé. avec dot et tout a commencé à fonctionner.

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

Si vous utilisez le cache interne, utilisez.

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

Cela peut résoudre le problème de Everyones:

<?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>
21
Mitul Varmora

Vérifiez le nombre de mémoires proposées par votre appareil - le partage de fichiers à partir d'un stockage secondaire n'est pas pris en charge. Regardez FileProvider.Java source (de support-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];
                }
            }

Alors, ils ne prennent que le premier stockage.

En outre, vous pouvez voir que getExternalCacheDirs() est utilisé pour obtenir la liste des stockages via l'interface ContextCompat. Voir documentation pour ses limites (il est dit de ne pas reconnaître les clés USB, par exemple). Le mieux est de créer vous-même une sortie de débogage de la liste des stockages à partir de cette API, afin que vous puissiez vérifier que le chemin d'accès au stockage correspond au chemin transmis à getUriForFile().

Il existe déjà un ticket affecté (comme pour 06-2017) dans le suivi des problèmes de Google, demandant de prendre en charge plusieurs systèmes de stockage. Finalement, j'ai trouvé SO question à ce sujet aussi.

13
lef

Cela me confond un peu aussi.

Le problème est sur l'attribut "chemin" dans votre fichier XML.

À partir de ce document FileProvider 'Chemin' est un sous-répertoire, Mais dans un autre document (appareil photo/base photographique) affiché 'Chemin' est un chemin complet.

<?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>

Je viens de changer ce "chemin" en chemin complet et cela fonctionne.

12
Supakij

Je suis sûr que je suis en retard à la fête, mais ci-dessous a fonctionné pour moi.

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

Je serais en retard, mais j'ai trouvé une solution pour cela. Travaillant bien pour moi, je viens de changer le fichier XML des chemins en:

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

Vous avez perdu 2 semaines à essayer de trouver une solution ... Si vous arrivez après avoir essayé l'une des solutions ci-dessus:

1 - Vérifiez si votre fournisseur de tags est dans l'application de tag

<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 - Si vous essayez beaucoup de chemins sans succès, alors testez ceci:

<?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>

Testez ceci, si la caméra fonctionne, commencez à éliminer certaines lignes et continuez les tests ...

- Ne pas oublier de vérifier si la caméra est activée dans votre émulateur.

9
Diego Venâncio

Sachez que external-path ne pointe pas sur votre stockage secondaire, également appelé "stockage amovible" (malgré le nom "externe"). Si vous obtenez "Échec de la recherche de la racine configurée", vous pouvez ajouter cette ligne à votre fichier XML.

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

Voir plus de détails ici FileProvider et stockage externe secondaire

6
Peter Shashkin

Mon problème était que j'avais des noms qui se chevauchaient dans les chemins de fichiers pour différents types, comme ceci:

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

Après avoir changé les noms ("cached_files") pour qu'ils soient uniques, je me suis débarrassé de l'erreur. Je suppose que ces chemins sont stockés dans une carte HashMap ou quelque chose qui n'autorise pas les doublons.

5
Jeopardy

Rien de tout cela n'a fonctionné pour moi. La seule approche qui fonctionne consiste à ne pas déclarer un chemin explicite en xml. Alors faites ceci et soyez heureux:

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

Voici aussi un excellent tutoriel sur cette question: https://www.youtube.com/watch?v=9ZxRTKvtfnY&t=613s

Ce que j'ai fait pour résoudre ceci -

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 (permettant au fournisseur de fichiers de partager tous les fichiers contenus dans le répertoire de fichiers externes de l'application)

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

et en classe Java -

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

Cela a fonctionné pour moi aussi. Au lieu de donner le chemin complet, j'ai donné path = "Pictures" et cela a bien fonctionné.

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

J'ai passé 5 heures pour cela ..

Vous n'avez pas lu les documents. J'ai essayé toutes les méthodes ci-dessus, mais cela dépend du stockage que votre application utilise actuellement. 

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

Consultez la documentation avant d'essayer les codes. 

Dans mon cas .__ puisque files-path sous-répertoire sera Context.getFilesDir(). Ce qui est génial, c’est que Context.getFilesDir() note un autre sous-répertoire. 

ce que je cherche c'est 

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

Context.getFilesDir()

retourne /data/user/0/com.psh.mTest/files

donc l'étiquette devrait être 

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

Alors ça marche !!

Lire la documentation !!

2
Seho Park

aucune des solutions ci-dessus n'a fonctionné pour moi, après plusieurs heures de débogage, j'ai découvert que le problème se trouvait dans createImageFile(), plus précisément absolute path vs relative path

Je suppose que vous utilisez le guide Android officiel pour prendre des photos. 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;
    }

Prenez note de la storageDir, il s’agit de l’emplacement où le fichier sera créé. Donc, pour obtenir le chemin absolu de ce fichier, j'utilise simplement image.getAbsolutePath(), ce chemin sera utilisé dans onActivityResult si vous avez besoin de l'image bitmap après avoir pris une photo.

ci-dessous est le file_path.xml, utilisez simplement . pour qu’il utilise le chemin absolu

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

et si vous avez besoin du bitmap après avoir pris une photo

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();
        }
    }
2
grandia

La modification suivante dans le fichier XML file_paths a fonctionné pour moi.

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

Mon problème était un nom de fichier incorrect: Je crée file_paths.xml sous res/xml alors que la ressource était configurée sur provider_paths.xml dans Manifest:

<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>

J'ai changé provider_paths en file_paths et le problème a été résolu.

1

Le document officiel Android indique que file_paths.xml devrait avoir: 

<?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>

Mais pour que cela fonctionne dans le dernier Android, il devrait y avoir un "/" à la fin du chemin, comme ceci:

<?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>
1
Shripad Bhat

Je recevais cette erreur Failed to find configured root that contains...

Le travail suivant résout mon problème

res/xml/chemin_fichiers.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)));
    }
0
Ali Tamoor

Cela dépend du type de stockage que vous voulez faire, INTERNE ou EXTERNE

pour le stockage externe 

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

mais pour INTERNAL STORAGE, faites attention au chemin, car il utilise la méthode getFilesDir (), qui signifie que votre fichier sera situé dans le répertoire racine de l'application ("/")

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

Donc, votre fichier de fournisseur doit être comme ceci:

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

Je trouve enfin mon problème. Je l'ai décrit dans le ce lien.

mon problème était la différence entre l'identifiant d'application en mode debug et release

0
saleh sereshki

Vous devez vous assurer que le contenu de votre fichier file_paths.xml contient la chaîne => "/Android/data/com.example.marek.myapplication/files/Pictures/"

À partir du message d'erreur, c'est le chemin où vos images sont stockées. Voir échantillon de prévu

files_path.xml ci-dessous:

<external-path name="qit_images" path="Android/data/com.example.marek.myapplication/files/Pictures/" />
0
Oladipo Olasemo

Bonjour amis Essayez ceci

Dans ce code

1) Comment déclarer le fournisseur de fichiers 2 dans Manifest.

2) Premier fournisseur pour le téléchargement de fichier 

3) deuxième fournisseur utilisé pour la caméra et gallary

ÉTAPE 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>

Deuxième fournisseur

     <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>

chemin_fichier.xml

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

.Utils.MyFileProvider

Create Class MyFileProvider (uniquement Create class no any method declare)

Lorsque vous avez utilisé le fournisseur de fichiers (.fileprovider), vous avez utilisé ce nom et vous avez utilisé l'image (.provider).

SI un problème à comprendre ce code, vous pouvez contacter sur [email protected], je vais vous aider.

0
Rahul Patil

Si rien ne vous aide et que vous obtenez l'erreur

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

puis essayez de changer une ligne comme:

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

à:

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

et dans le fichier xml:

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

ce qui est bizarre, puisque le dossier auquel j’accède est /images.

0
LivinTheNoobLife

Le problème ne réside peut-être pas uniquement dans le chemin XML.

Voici ma solution:

Recherche dans le cours racine dans 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);
        }

        // ...
    }

Cela signifie que mRoots devrait contenir la balise de l'URI demandé. Alors j'écris du code pour imprimer mRoots et la balise de uri, puis trouve facilement les balises ne correspondent pas .

Il s'avère que définir l'autorité du fournisseur sur ${applicationID}.provider est une idée stupide ! Cette autorité est si courante qu'elle pourrait être utilisée par d'autres fournisseurs, ce qui perturberait la configuration du chemin d'accès!

0
thundertrick

J'ai remarqué que la politique ou le comportement concernant le fichier path.xml avait changé entre les bibliothèques de support 26 et 27. Pour capturer une image à partir de l'appareil photo, j'ai constaté les changements suivants: 

  • Avec 26, je devais utiliser <external-path> et le chemin complet indiqué dans l'argument path.

  • Avec 27, je devais utiliser <external-files-path> et uniquement le sous-dossier de l'argument path.

Donc, ce qui a fonctionné spécifiquement pour moi avec Support Library 27 en tant que fichier path.xml était 

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-files-path name="camera_image" path="Pictures/"/>
</paths>
0
Johan Paul
  • Pour les utilisateurs de Xamarin.Android

Cela pourrait également être le résultat de la non mise à jour de vos packages de support lorsque vous ciblez Android 7.1, 8.0+. Mettez-les à jour avec v25.4.0.2 + et cette erreur pourrait disparaître (en vous configurant correctement le fichier chemin_fichier comme indiqué par d’autres).


Donner le contexte: je suis passé au ciblage Oreo de Nougat dans un Xamarin.Forms app et prendre une photo avec le Xam.Plugin.Media commencé à échouer avec le message d'erreur ci-dessus, donc mise à jour des packages a fait le tour pour moi ok.

0
Ahmed Alejo

J'ai eu le même problème, j'ai essayé le code ci-dessous pour son fonctionnement.

1.Create Xmlfile: provider_paths

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

2. Fichier 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.Dans votre fichier 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);
0
Suresh kumar

Je constate qu'au moins vous ne fournissez pas le même chemin que d'autres dans file_paths.xml . Assurez-vous donc de fournir exactement le même nom de package ou le même chemin à trois endroits, notamment:

  • Android:authorities attribut dans le manifeste
  • path attribut dans chemin_fichiers.xml
  • authority lors de l'appel de FileProvider.getUriForFile ().
0
Pei

Vous devez modifier le fichier XML file_paths.xml à partir de

<?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>
0
Andrey