android.os.FileUriExposedException: file:///... exposed beyond app through Intent.getData() bedeutet, dass die App eine file://-URI über einen Intent oder einen vergleichbaren appübergreifenden Ablauf aus ihrem eigenen Prozess heraus weitergegeben hat. Android löst diese Diagnoseausnahme für Apps aus, die auf Android N beziehungsweise API-Level 24 oder höher ausgerichtet sind. Prüfen Sie als sicherste erste Maßnahme die Intent-Daten, EXTRA_STREAM, ClipData und sämtliche Ausgabe-URIs der Kamera auf verbliebene file://-Werte, bevor Sie Provider-Einstellungen ändern. Der konkrete Dateipfad und der am Ende der Meldung genannte Intent-Zugriff können je nach betroffenem Ablauf abweichen.
Was android.os.FileUriExposedException bedeutet
Die Ausnahme betrifft die appübergreifende Offenlegung von Dateien und nicht jeden Fehler beim Dateizugriff unter Android. Sie tritt häufig bei ACTION_VIEW, ACTION_SEND, ACTION_SEND_MULTIPLE, Kameraaufnahmen, Anhängen, Druckvorgängen und Abläufen über das Android Sharesheet auf.
Die Ausnahme wurde mit API-Level 24 eingeführt und wird bei Apps ausgelöst, die auf Android N oder höher ausgerichtet sind. Die Android-Version des Geräts und die targetSdkVersion der App sind miteinander verbundene Bedingungen, dürfen aber nicht gleichgesetzt werden. Die Android-Referenz zu FileUriExposedException nennt als unterstützten Ersatz eine content://-URI mit temporärem Zugriff für die Empfänger-App.
Dass die Ausnahme bei einer anderen SDK-Konfiguration nicht auftritt, macht die Freigabe über file:// nicht sicher. Android beschreibt die Ausnahme als Diagnosehilfe und nicht als eigenständigen Sicherheitsmechanismus.
Die file://-URI ermitteln, die die App verlässt
Wann dies zutrifft: Führen Sie diese Prüfung vor der Konfiguration von FileProvider durch. Das gilt auch, wenn die Meldung mit Intent.getData() oder ClipData.Item.getUri() endet.
Voraussetzungen: Der Text der Ausnahme und der Quellcode des ausgehenden Intent-Ablaufs.
- Prüfen Sie die in der Ausnahme ausgegebene URI und bestätigen Sie, dass ihr Schema
filelautet. - Prüfen Sie die Einträge des Anwendungs-Codes unmittelbar vor der Ausnahme im Stacktrace, um die Stelle zu finden, an der die ausgehende URI erstellt oder angefügt wird.
- Suchen Sie nach
Uri.fromFile()und nach dem Parsen eines Werts, der mitfile://beginnt. - Prüfen Sie die Intent-Daten,
EXTRA_STREAM, jedesClipData-Element und sämtliche Ausgabe-URIs der Kamera jeweils separat. - Notieren Sie die Quelle und den tatsächlichen Speicherort der Datei. Davon hängt ab, ob eine bereits autorisierte URI oder FileProvider geeignet ist.
Erwartetes Ergebnis: Sie haben jede file://-URI im fehlschlagenden Ablauf sowie die Stelle ermittelt, an der sie jeweils in den Intent gelangt.
Risiko und Warnung: Dies ist ein rein lesender Diagnoseschritt. Gehen Sie nicht davon aus, dass eine Änderung der Intent-Daten genügt, wenn ein anderes URI-führendes Feld unverändert bleibt. Ob ClipData beteiligt ist, muss am tatsächlichen Intent geprüft werden.
Die richtige Quelle für die Content-URI auswählen
Wann diese Lösung zutrifft: Verwenden Sie diesen Weg, wenn die Quelle bereits eine autorisierte content://-URI bereitstellt, beispielsweise für ein vom Nutzer ausgewähltes Dokument oder ein freigegebenes Medienelement.
Voraussetzungen: Stellen Sie sicher, dass die vorhandene URI weiterhin für den vorgesehenen Vorgang autorisiert ist.
- Behalten Sie die vorhandene
content://-URI bei, anstatt sie in einen Dateisystempfad umzuwandeln. - Verwenden Sie das Storage Access Framework für Dokumente, die der Nutzer ausgewählt hat.
- Verwenden Sie für freigegebene Medien eine geeignete MediaStore-URI.
- Fügen Sie diese autorisierte URI in das erforderliche Intent-Feld ein und fahren Sie anschließend mit den unten beschriebenen Prüfungen der temporären Berechtigungen fort.
Erwartetes Ergebnis: Der appübergreifende Ablauf behält eine autorisierte content://-URI bei, ohne einen neuen FileProvider einzuführen.
Risiko und Rückgängigmachen: Das Risiko ist gering. Wenn die Quelle keine für den Vorgang geeignete autorisierte URI bereitstellen kann, verwenden Sie FileProvider nur, wenn die Datei der App gehört. Leiten Sie nicht standardmäßig jeden Pfad über FileProvider.
AndroidX FileProvider im Manifest konfigurieren
Wann diese Lösung zutrifft: Verwenden Sie AndroidX FileProvider, wenn eine Datei der App gehört und für eine andere App freigegeben werden muss.
Voraussetzungen: AndroidX FileProvider muss verfügbar sein, Sie müssen das Manifest bearbeiten können und eine XML-Ressource für die Provider-Pfade anlegen können. Die genaue Authority ist appabhängig.
- Deklarieren Sie einen Provider, dessen
android:nameFileProvider oder die FileProvider-Unterklasse der App ist. - Setzen Sie
android:authoritiesauf eine appspezifische Authority. - Setzen Sie
android:exported="false". - Setzen Sie
android:grantUriPermissions="true". - Fügen Sie den FileProvider-Metadateneintrag hinzu, der auf die XML-Ressource mit den Provider-Pfaden verweist.
- Stellen Sie sicher, dass die später zur URI-Erzeugung verwendete Authority exakt mit der Authority im Manifest übereinstimmt.
Die Dokumentation zu AndroidX FileProvider beschreibt dieses Provider-Modell und die zugehörigen temporären URI-Berechtigungen.
Erwartetes Ergebnis: Die App verfügt über einen nicht exportierten Provider, der für konfigurierte Dateien autorisierte content://-URIs erzeugen kann.
Risiko und Rückgängigmachen: Das Risiko ist gering. Entfernen Sie den Provider und seine Metadaten, wenn die Freigabefunktion entfernt wird. Veröffentlichen oder übernehmen Sie keinen universellen Authority-Wert, da dieser mit der Konfiguration der App übereinstimmen muss.
Die file_paths-XML auf die freizugebenden Dateien beschränken
Wann diese Lösung zutrifft: Führen Sie diesen Schritt immer aus, wenn FileProvider verwendet wird.
Voraussetzungen: Sie müssen das genaue Verzeichnis kennen, in dem sich die freizugebende Datei befindet.
- Definieren Sie nur das Verzeichnis oder die Verzeichnisse, die für die Freigabefunktion erforderlich sind.
- Wählen Sie möglichst das engste Verzeichnis, das die vorgesehene Datei noch enthält.
- Vermeiden Sie weit gefasste Stammverzeichnisse, die nicht zugehörige App-Dateien oder Dateien im gemeinsam genutzten Speicher einschließen.
- Prüfen Sie vor dem Erzeugen der Content-URI, ob die Datei innerhalb eines der konfigurierten Stammverzeichnisse aufgelöst wird.
Der genaue XML-Eintrag kann nicht allgemeingültig vorgegeben werden, da er vom Speicherort der Datei in der App abhängt. Die offiziellen Hinweise zu den Änderungen bei der Offenlegung von Datei-URIs unter Android 7.0 empfehlen die Migration zu FileProvider, anstatt Datei-URIs weiterhin offenzulegen.
Erwartetes Ergebnis: FileProvider kann die vorgesehene Datei auflösen, während nicht zugehörige Speicherorte außerhalb seines konfigurierten Geltungsbereichs bleiben.
Risiko und Rückgängigmachen: Das Risiko ist mittel, da ein zu weit gefasstes Stammverzeichnis mehr Dateien als vorgesehen zugänglich machen kann. Schränken Sie die Pfade in der XML-Datei ein, wenn eine Prüfung oder ein Test eine übermäßige Abdeckung zeigt. Erweitern Sie sie nicht nur, um einen Fehler wegen eines nicht konfigurierten Stammverzeichnisses zu umgehen.
file:// ersetzen und nur den erforderlichen temporären Zugriff gewähren
Die FileProvider-Content-URI erzeugen und anfügen
Wann diese Lösung zutrifft: Verwenden Sie sie, nachdem die Manifest-Authority und eng begrenzte Provider-Pfade für eine app-eigene Datei konfiguriert wurden.
Voraussetzungen: Die Datei muss sich innerhalb eines zulässigen Provider-Stammverzeichnisses befinden, und die zur URI-Erzeugung verwendete Authority muss mit dem Manifest übereinstimmen.
- Erzeugen Sie die URI mit FileProvider statt mit
Uri.fromFile()oder einem manuell erstelltenfile://-Wert. - Fügen Sie die resultierende
content://-URI in die Intent-Daten,EXTRA_STREAModer das vom vorhandenen Ablauf benötigte Kamera-Ausgabefeld ein. - Ersetzen Sie bei mehreren Dateien jede offengelegte URI und nicht nur das erste Element.
- Prüfen Sie
ClipDataund alle anderen URI-führenden Felder, damit die alte Datei-URI nicht an anderer Stelle erhalten bleibt.
Erwartetes Ergebnis: Der ausgehende Intent enthält content://-URIs von FileProvider anstelle von file://-URIs.
Risiko und Rückgängigmachen: Das Risiko ist gering, und bei diesem Vorgang wird die Datei nicht gelöscht. Stellen Sie die appübergreifende Freigabe über file:// in einer Produktionsumgebung nicht wieder her. Die vorherige URI-Quelle eignet sich nur für isolierte lokale Diagnosen, bei denen die URI die App nicht verlässt.
Temporäre URI-Berechtigungen gewähren
Wann diese Lösung zutrifft: Verwenden Sie temporäre Berechtigungen, wenn die Empfänger-App den vom Intent referenzierten Inhalt lesen oder ändern muss.
Voraussetzungen: Der Intent muss eine gültige content://-URI enthalten, und die erforderliche Zugriffsstufe des Empfängers muss bekannt sein.
- Fügen Sie
FLAG_GRANT_READ_URI_PERMISSIONhinzu, wenn der Empfänger die Datei lesen muss. - Fügen Sie
FLAG_GRANT_WRITE_URI_PERMISSIONnur hinzu, wenn der Empfänger die Datei ändern muss. - Fügen Sie die URI über
ClipDataan, wenn dies im unterstützten Ablauf für die Weitergabe der Berechtigung erforderlich ist. - Fügen Sie keine weitergehenden Dateisystemberechtigungen oder Schreibrechte hinzu, die für den Vorgang nicht erforderlich sind.
Erwartetes Ergebnis: Der Empfänger erhält den erforderlichen temporären Mindestzugriff, während der Provider nicht exportiert bleibt.
Risiko und Rückgängigmachen: Bei eng begrenztem Zugriff ist das Risiko gering. Entfernen Sie Schreib- oder Leseberechtigungs-Flags, sobald der Empfänger die jeweilige Berechtigung nicht mehr benötigt. Die Berechtigungsweitergabe über ClipData hängt vom jeweiligen Ablauf ab und muss auf den unterstützten Android-Versionen getestet werden.
Prüfen, ob die Empfänger-App auf die Content-URI zugreifen kann
Wann dies zutrifft: Prüfen Sie den vollständigen Ablauf, nachdem Sie die URI ersetzt und die temporären Berechtigungen gesetzt haben.
Voraussetzungen: Die vorgesehene Empfängerkomponente muss für den Test verfügbar sein.
- Stellen Sie sicher, dass jede ausgehende URI das Schema
contentverwendet. - Stellen Sie sicher, dass die Authority der erzeugten URI exakt mit der im Manifest deklarierten Provider-Authority übereinstimmt.
- Stellen Sie sicher, dass sich die Datei innerhalb eines konfigurierten Provider-Stammverzeichnisses befindet.
- Prüfen Sie die Intent-Daten,
EXTRA_STREAM,ClipDataund Ausgabe-URIs erneut auf verbliebenefile://-Werte. - Testen Sie die tatsächliche Empfänger-App mit Leseberechtigung und fügen Sie die Schreibberechtigung nur hinzu, wenn Änderungen erforderlich sind.
- Stellen Sie sicher, dass der Empfänger den vorgesehenen Vorgang ausführen kann, ohne das Provider-Stammverzeichnis oder die Berechtigungen zu erweitern.
Erwartetes Ergebnis: Der ausgehende Ablauf legt keine Datei-URI mehr offen, und die Empfängerkomponente kann mit der erforderlichen Mindestberechtigung auf die autorisierte Content-URI zugreifen. Dies muss durch Tests bestätigt werden; eine Änderung des Schemas allein gewährleistet noch keinen Zugriff durch den Empfänger.
Risiko und Warnung: Die Prüfung ist mit einem geringen Risiko verbunden. Wenn die ursprüngliche Ausnahme nicht mehr auftritt, der Zugriff aber weiterhin fehlschlägt, prüfen Sie die Authority, die Provider-Metadaten, die konfigurierten Pfade, die URI-Berechtigungen und den tatsächlichen Dateispeicherort manuell. Unterdrücken Sie die Erkennung nicht mit StrictMode.VmPolicy, setzen Sie die targetSdkVersion nicht herab, geben Sie keine weit gefassten Stammverzeichnisse frei und gewähren Sie nicht standardmäßig Schreibzugriff. Diese Maßnahmen verbergen oder verschärfen das Problem, statt den appübergreifenden Freigabeablauf zu korrigieren.

