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.
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>
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>
Si vous utilisez le cache interne, utilisez.
<paths xmlns:Android="http://schemas.Android.com/apk/res/Android">
<cache-path name="cache" path="/" />
</paths>
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>
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.
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.
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>
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>
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.
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
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.
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);
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>
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 !!
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();
}
}
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"/>
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.
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>
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)));
}
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
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/" />
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.
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
.
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!
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>
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.
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);
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 manifestepath
attribut dans chemin_fichiers.xmlauthority
lors de l'appel de FileProvider.getUriForFile ().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>