FileProvider - IllegalArgumentException: No se pudo encontrar la raíz configurada

Estoy intentando hacer una foto con la cámara, pero me sale el siguiente error:

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);
        }
    }

file_paths.xml

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

Estuve buscando todo el día sobre este error y tratando de entender FileProvider, pero no tengo idea de lo que este mensaje de error trata de decirme. Si quieres más información/código, escríbeme en el comentario.

Solución

Su archivo está almacenado en getExternalFilesDir(). Eso se corresponde con `

Comentarios (16)

Esto también me confunde un poco.

El problema está en "path" atributo en su archivo xml.

De este documento FileProvider 'path' es un subdirectorio, pero en otro documento (camera/photobasics) se muestra 'path' es la ruta completa.

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

Acabo de cambiar esta 'ruta' a la ruta completa y sólo funciona.

Comentarios (0)

Comprueba cuántos almacenamientos ofrece tu dispositivo - compartir archivos desde el almacenamiento secundario no está soportado. Mira la fuente FileProvider.java (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];
                }
            }

Por lo tanto, toman sólo el primer almacenamiento.

Además, puedes ver que getExternalCacheDirs() se utiliza para obtener la lista de almacenamientos a través de la interfaz ContextCompat. Ver la documentación para sus límites (se dice que no reconoce los USB Flashes por ejemplo). Lo mejor es hacer alguna salida de depuración de la lista de almacenamientos de esta API por su cuenta, para que pueda comprobar que la ruta al almacenamiento coincide con la ruta pasada a getUriForFile().

Ya hay un ticket asignado (a partir del 06-2017) en el gestor de incidencias de Google's, pidiendo que se admita más de un almacenamiento. Eventualmente, encontré SO question on this también.

Comentarios (1)