expuesto más allá de la aplicación a través de ClipData.Item.getUri


99

Estoy tratando de solucionar un problema después de que se agregó la nueva función en el sistema de archivos de Android, pero aparece este error:

android.os.FileUriExposedException: file:///storage/emulated/0/MyApp/Camera_20180105_172234.jpg exposed beyond app through ClipData.Item.getUri()

Así que espero que alguien pueda ayudarme a solucionar este problema :)

Gracias

private Uri getTempUri() {
    // Create an image file name
    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
    String dt = sdf.format(new Date());
    imageFile = null;
    imageFile = new File(Environment.getExternalStorageDirectory()
            + "/MyApp/", "Camera_" + dt + ".jpg");
    AppLog.Log(
            TAG,
            "New Camera Image Path:- "
                    + Environment.getExternalStorageDirectory()
                    + "/MyApp/" + "Camera_" + dt + ".jpg");
    File file = new File(Environment.getExternalStorageDirectory() + "/MyApp");
    if (!file.exists()) {
        file.mkdir();
    }
    imagePath = Environment.getExternalStorageDirectory() + "/MyApp/"
            + "Camera_" + dt + ".jpg";
    imageUri = Uri.fromFile(imageFile);
    return imageUri;
}

Respuestas:


170

Para sdk 24 y posteriores, si necesita obtener el Uri de un archivo fuera del almacenamiento de su aplicación, tiene este error.
Las soluciones de @ eranda.del le permiten cambiar la política para permitir esto y funciona bien.

Sin embargo, si desea seguir las pautas de Google sin tener que cambiar la política de API de su aplicación, debe usar un FileProvider.

Al principio, para obtener el URI de un archivo, debe usar el método FileProvider.getUriForFile ():

Uri imageUri = FileProvider.getUriForFile(
            MainActivity.this,
            "com.example.homefolder.example.provider", //(use your app signature + ".provider" )
            imageFile);

Entonces necesitas configurar tu proveedor en tu manifiesto de Android:

<application>
  ...
     <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="com.example.homefolder.example.provider"
        android:exported="false"
        android:grantUriPermissions="true">
        <!-- ressource file to create -->
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths">  
        </meta-data>
    </provider>
</application>

(En "autoridades", use el mismo valor que el segundo argumento del método getUriForFile () (firma de la aplicación + ".provider"))

Y finalmente necesitas crear el archivo de recursos: "file_paths". Este archivo debe crearse en el directorio res / xml (probablemente también necesite crear este directorio):

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

79
"Facilite la vida a los desarrolladores": este es el lema de cada API nueva, ¿verdad Google?
Kirill Karmazin

12
La solución proporcionada por Brendon es la correcta, pero no está lista para copiar y pegar, por ejemplo, debe verificar si se adapta a sus necesidades. <external-path ...se utiliza cuando se desea Environment.getExternalStorageDirectory (). y utilícelo <files-path ...si necesita Context.getFilesDir (). Es mejor que primero consulte los documentos oficiales: developer.android.com/reference/android/support/v4/content/…
Kirill Karmazin

9
Un recordatorio si está utilizando androidx (nuevo espacio de nombres de soporte), puede encontrar aquí ( developer.android.com/reference/androidx/core/content/… ) la documentación adecuada.
Rodrirokr

20
Tenga en cuenta que en androidxél está:android:name="androidx.core.content.FileProvider"
smörkex

150

Agregue el siguiente bloque de código antes de iniciar la cámara o la exploración de archivos

    StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
    StrictMode.setVmPolicy(builder.build());

Consulte el modo estricto del enlace de referencia y se explican todos los detalles técnicos y de uso.


24
No es la forma correcta de resolver esto, esto básicamente eliminará las políticas de modo estricto. e ignorará la advertencia de seguridad
Ahsan Zaheer

Hay algunos pros y contras en esto. Consulte lo siguiente para obtener más información stackoverflow.com/questions/18100161/…
eranda.del

Funciona, si hay algún inconveniente, hágamelo saber :)
Hanan

El código resolvió la excepción para mí. Sin embargo, el comentario superior aquí dice que el código no es la forma correcta de resolver esto. ¿Alguien sabe cuál sería el método adecuado entonces?
Shn_Android_Dev

Google odia a los programadores.
Joubert Vasconcelos

0

No se debe permitir ninguna configuración de proveedor requerida en AndroidManifest only Camera and Storage. Utilice el siguiente código para iniciar la cámara:

final int REQUEST_ACTION_CAMERA = 9;
void openCamra() {
Intent cameraImgIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

cameraImgIntent.putExtra(MediaStore.EXTRA_OUTPUT,
                FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID +".provider",
                new File("your_file_name_with_dir")));
startActivityForResult(cameraImgIntent, REQUEST_ACTION_CAMERA);
}

Después de capturar la imagen, puede encontrar su imagen capturada en:

"your_file_name_with_dir"

Es mejor explicar la configuración del proveedor en AndroidManifest que dar otro código.
fury.slay
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.