über die App hinaus über ClipData.Item.getUri verfügbar gemacht

99

Ich versuche, ein Problem zu beheben, nachdem die neue Funktion im Android-Dateisystem hinzugefügt wurde, aber ich erhalte folgende Fehlermeldung:

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

Ich hoffe, jemand kann mir helfen, das zu beheben :)

Vielen Dank

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

Antworten:

166

Ab SDK 24 tritt dieser Fehler auf, wenn Sie den Uri einer Datei außerhalb Ihres App-Speichers abrufen müssen.
Mit @ eranda.del-Lösungen können Sie die Richtlinie ändern, um dies zu ermöglichen, und es funktioniert einwandfrei.

Wenn Sie jedoch der Google-Richtlinie folgen möchten, ohne die API-Richtlinie Ihrer App ändern zu müssen, müssen Sie einen FileProvider verwenden.

Um den URI einer Datei zu erhalten, müssen Sie zunächst die FileProvider.getUriForFile () -Methode verwenden:

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

Dann müssen Sie Ihren Provider in Ihrem Android-Manifest konfigurieren:

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

(Verwenden Sie in "Behörden" denselben Wert wie im zweiten Argument der Methode getUriForFile () (App-Signatur + ".provider").)

Und schließlich müssen Sie die Ressourcendatei "file_paths" erstellen. Diese Datei muss im Verzeichnis res / xml erstellt werden (wahrscheinlich müssen Sie auch dieses Verzeichnis erstellen):

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_files" path="." />
</paths>
Brendon
quelle
77
"Machen Sie Entwicklern das Leben leichter" - das ist der Slogan für jede neue API, oder Google?
Kirill Karmazin
12
Die von Brendon bereitgestellte Lösung ist die richtige, aber nicht zum Kopieren und Einfügen bereit. Sie müssen beispielsweise prüfen, ob sie Ihren Anforderungen entspricht. <external-path ...wird verwendet, wenn Sie Environment.getExternalStorageDirectory () möchten. und verwenden <files-path ...Sie, wenn Sie Context.getFilesDir () benötigen. Sie sollten zuerst die offiziellen Dokumente überprüfen: developer.android.com/reference/android/support/v4/content/…
Kirill Karmazin
9
Eine Erinnerung, wenn Sie androidx (neuer Support-Namespace) verwenden, finden Sie hier ( developer.android.com/reference/androidx/core/content/… ) die richtige Dokumentation.
Rodrirokr
18
Beachten Sie, dass androidxdarin:android:name="androidx.core.content.FileProvider"
smörkex
150

Fügen Sie den folgenden Codeblock hinzu, bevor Sie mit dem Durchsuchen der Kamera oder der Datei beginnen

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

Bitte beziehen Sie sich auf den strengen Verweislink- Modus und erläutern Sie alle Verwendungs- und technischen Details.

eranda.del
quelle
24
Dies ist nicht der richtige Weg, um dies zu lösen. Dadurch werden im Grunde genommen die Richtlinien für den strengen Modus entfernt. und wird die Sicherheitswarnung ignorieren
Ahsan Zaheer
Hier gibt es einige Vor- und Nachteile. Weitere Informationen finden
eranda.del
Es funktioniert, wenn es einen Nachteil gibt, lassen Sie es mich bitte wissen :)
Hanan
Der Code hat die Ausnahme für mich gelöst. Der oberste Kommentar hier sagt jedoch, dass der Code nicht der richtige Weg ist, um dies zu lösen. Weiß jemand, was dann die richtige Methode wäre?
Shn_Android_Dev
Google hasst Programmierer.
Joubert Vasconcelos
0

Es ist keine erforderliche Anbieterkonfiguration in AndroidManifest nur für Kamera- und Speicherberechtigungen zulässig. Verwenden Sie den folgenden Code, um die Kamera zu starten:

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

Nach der Aufnahme des Bildes finden Sie das aufgenommene Bild in:

"your_file_name_with_dir"
Hemraj Patel
quelle
Es ist besser, die Konfiguration des Anbieters in AndroidManifest zu erklären, als anderen Code anzugeben.
fury.slay