esposto oltre l'app tramite ClipData.Item.getUri


99

Sto cercando di risolvere un problema dopo che la nuova funzionalità è stata aggiunta nel file system Android ma ottengo questo errore:

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

Quindi spero che qualcuno possa aiutarmi a risolvere questo problema :)

Grazie

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

Risposte:


166

Per SDK 24 e versioni successive, se è necessario ottenere l'URI di un file al di fuori della memoria dell'app, si verifica questo errore.
Le soluzioni @ eranda.del consentono di modificare la politica per consentirlo e funziona correttamente.

Tuttavia, se vuoi seguire le linee guida di Google senza dover modificare la policy API della tua app, devi utilizzare un FileProvider.

All'inizio per ottenere l'URI di un file è necessario utilizzare il metodo FileProvider.getUriForFile ():

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

Quindi devi configurare il tuo provider nel tuo manifest 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>

(In "autorità" utilizzare lo stesso valore del secondo argomento del metodo getUriForFile () (firma dell'app + ".provider"))

E infine è necessario creare il file delle risorse: "file_paths". Questo file deve essere creato nella directory res / xml (probabilmente dovrai creare anche questa directory):

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

78
"Semplifica la vita degli sviluppatori": questo è lo slogan di ogni nuova API, vero Google?
Kirill Karmazin

12
La soluzione fornita da Brendon è quella corretta ma non è pronta per il copia-incolla, è necessario verificare se è adatta alle proprie esigenze, ad es. <external-path ...viene utilizzato quando si desidera Environment.getExternalStorageDirectory (). e usa <files-path ...se hai bisogno di Context.getFilesDir (). È meglio controllare prima i documenti ufficiali: developer.android.com/reference/android/support/v4/content/…
Kirill Karmazin

9
Un promemoria se stai utilizzando androidx (nuovo spazio dei nomi di supporto), puoi trovare qui ( developer.android.com/reference/androidx/core/content/… ) la documentazione appropriata.
Rodrirokr

19
Si noti che in androidxesso è:android:name="androidx.core.content.FileProvider"
smörkex

150

Aggiungi il seguente blocco di codice prima di avviare la fotocamera o la ricerca di file

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

Si prega di fare riferimento alla modalità rigorosa del link di riferimento e di spiegare tutti i dettagli tecnici e di utilizzo.


24
Non è il modo giusto per risolvere questo problema, questo sostanzialmente rimuoverà le politiche rigorose. e ignorerà l'avviso di sicurezza
Ahsan Zaheer

Ci sono alcuni pro e contro su questo. Fare riferimento al seguente per avere maggiori informazioni stackoverflow.com/questions/18100161/...
eranda.del

Funziona, se c'è qualche problema, fammelo sapere :)
Hanan

Il codice ha risolto l'eccezione per me. Tuttavia, il commento in alto qui dice come il codice non è il modo corretto per risolvere questo problema. Qualcuno sa quale sarebbe il metodo corretto allora?
Shn_Android_Dev

Google odia i programmatori.
Joubert Vasconcelos

0

Nessuna configurazione del provider richiesta in AndroidManifest deve essere consentita solo l'autorizzazione per fotocamera e archiviazione. Usa il codice seguente per avviare la fotocamera:

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

Dopo aver catturato l'immagine, puoi trovare l'immagine catturata in:

"your_file_name_with_dir"

È meglio spiegare la configurazione del provider in AndroidManifest, piuttosto che fornire altro codice.
furia
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.