Grundlagen der Dateispeicherung
Dateien gehören je nach Schutzbedarf und Nutzung an unterschiedliche Speicherorte. Du lernst die Grundregeln für interne Dateien, externe Dateien und Medien.
Dateispeicherung wirkt am Anfang wie eine kleine Detailfrage: Du hast Bytes und brauchst einen Ort dafür. In echten Android-Apps entscheidet dieser Ort aber über Datenschutz, Berechtigungen, Backup, Offline-Fähigkeit, Nutzervertrauen und Wartbarkeit. Die Grundregel lautet: Speichere Dateien dort, wo ihr Zweck, ihre Sichtbarkeit und ihre Lebensdauer zusammenpassen.
Was ist das?
File Storage Basics meint die grundlegende Entscheidung, wo eine Android-App Dateien ablegt. Dabei geht es nicht nur um Pfade, sondern um Verantwortung. Eine Datei kann privat zur App gehören, bewusst mit dem Nutzer geteilt werden oder ein öffentliches Medium sein, das auch andere Apps anzeigen dürfen.
Interne Dateien sind private App-Dateien. Sie liegen im app-spezifischen internen Speicher und sind normalerweise nur für deine App zugänglich. Typische Beispiele sind Cache-Daten, lokale JSON-Snapshots, Protokolle für Debug-Builds, exportierte Zwischenergebnisse oder Dateien, die deine Data Layer für Offline-Funktionen nutzt. Wenn die App deinstalliert wird, entfernt Android diese Daten in der Regel mit.
Externe Dateien liegen in einem Speicherbereich, der stärker auf Austausch und Nutzerkontrolle ausgelegt ist. Das bedeutet nicht automatisch, dass jede andere App freien Zugriff hat. Moderne Android-Versionen begrenzen Zugriffe stärker als früher. Trotzdem ist das mentale Modell wichtig: Externe Dateien sind eher für Daten gedacht, die der Nutzer wiederfinden, exportieren oder mit anderen Apps verwenden soll.
Medien sind ein eigener Fall. Fotos, Videos und Audiodateien gehören nicht einfach irgendwo in einen beliebigen Ordner, wenn sie Teil der Nutzerbibliothek sein sollen. Android stellt dafür strukturierte Mediensammlungen bereit, etwa über den MediaStore. So kann das System Metadaten verwalten, Galerie-Apps finden Bilder korrekt, und du vermeidest unnötig breite Dateiberechtigungen.
Im Android-Kontext hängt diese Entscheidung eng mit Architektur zusammen. Deine UI in Jetpack Compose sollte nicht wissen müssen, ob eine Datei intern, extern oder im MediaStore liegt. Diese Details gehören in Repositorys oder Datenquellen der Data Layer. So bleibt die Oberfläche testbar, und du kannst Speicherentscheidungen ändern, ohne jede Composable-Funktion anzufassen.
Wie funktioniert es?
Der wichtigste Gedanke ist: Speicherorte sind Verträge. Wenn du eine Datei intern speicherst, sagst du damit: Diese Daten gehören zur App und sind nicht für direkten Zugriff durch den Nutzer oder andere Apps gedacht. Wenn du eine Datei extern speicherst, sagst du: Diese Daten können einen Zweck außerhalb der App haben. Wenn du Medien über die passende Medien-API speicherst, sagst du: Diese Datei ist Teil der Medienwelt des Geräts.
Für interne Dateien nutzt du in Kotlin meist APIs, die vom Context ausgehen. filesDir ist für dauerhafte private Dateien gedacht. cacheDir ist für Daten gedacht, die Android oder deine App löschen darf, wenn Speicher knapp wird. Du solltest dort nichts ablegen, was fachlich unverzichtbar ist. Ein Offline-Cache kann dort liegen, wenn er jederzeit neu aufgebaut werden kann. Eine vom Nutzer erstellte Notiz sollte dort nicht liegen, wenn sie ohne Synchronisation sonst verloren wäre.
App-spezifische externe Dateien erreichst du über Methoden wie getExternalFilesDir(...). Diese Dateien sind stärker für Austausch oder größere Datenmengen geeignet, werden aber ebenfalls zur App gezählt. Sie können je nach Gerät, Android-Version und Nutzeraktion unterschiedlich sichtbar sein. Du solltest dich nicht darauf verlassen, dass ein manueller Dateipfad dauerhaft stabil bleibt. Nutze die Plattform-APIs und behandle URIs als wichtiger als rohe Pfadstrings.
Für Medien ist der MediaStore der zentrale Einstieg. Du legst dort Einträge mit Namen, MIME-Type und Ziel-Sammlung an. Danach schreibst du den Inhalt über einen ContentResolver. Dadurch landet ein Bild zum Beispiel in der Bildersammlung des Systems, statt nur als private Datei in deinem App-Verzeichnis. Das ist besonders wichtig, wenn der Nutzer erwartet, dass ein aufgenommenes oder erzeugtes Bild in der Galerie erscheint.
Berechtigungen sind ein häufiger Stolperpunkt. Früher wurde oft breit mit Leserechten auf externen Speicher gearbeitet. Moderne Android-Entwicklung verlangt deutlich feinere Entscheidungen. Wenn du nur eine eigene interne Datei liest, brauchst du keine Speicherberechtigung. Wenn der Nutzer eine Datei auswählt, ist ein System-Picker oft besser als eine allgemeine Berechtigung. Wenn du Medien verwaltest, solltest du die aktuellen, passenden Media-APIs nutzen, statt pauschal Zugriff auf möglichst viel Speicher zu verlangen.
Auch Sicherheit gehört zur Mechanik. Speichere sensible Daten nicht unnötig als Klartextdatei, besonders nicht in Bereichen, die exportiert oder geteilt werden. Tokens, personenbezogene Inhalte, Diagnosedaten und Geschäftsdaten brauchen eine bewusste Schutzentscheidung. Manchmal ist eine Datenbank mit klarer Zugriffsschicht besser als viele lose Dateien. Manchmal reicht eine interne Datei. Entscheidend ist, dass du den Schutzbedarf vor dem Schreiben klärst.
In einer sauberen Architektur kapselst du Dateizugriff. Eine FileRepository-Klasse kann entscheiden, ob ein Export in externe App-Dateien geht, ob ein Vorschaubild intern zwischengespeichert wird oder ob ein fertiges Foto über den MediaStore veröffentlicht wird. Die ViewModel-Schicht ruft nur fachliche Methoden auf, etwa saveDraftAttachment(...) oder exportReport(...). Dadurch bleiben Compose-Screens frei von Speicherlogik und Nebenwirkungen.
In der Praxis
Stell dir eine App vor, die einen Bericht als Textdatei zwischenspeichert und später optional exportiert. Während der Bearbeitung ist der Bericht privat. Er gehört also in den internen Speicher. Erst wenn der Nutzer aktiv exportiert, erzeugst du eine teilbare Datei oder gibst eine URI über einen passenden Android-Mechanismus weiter.
Entscheidungsregel
Nutze diese einfache Regel im Code-Review:
Private Arbeitsdaten deiner App speicherst du intern. Vom Nutzer bewusst weiterzuverwendende Dateien speicherst oder teilst du über externe, vom System vorgesehene Wege. Fotos, Videos und Audiodateien, die in der Medienbibliothek auftauchen sollen, speicherst du über MediaStore. Cache ist nur für Daten, die ohne fachlichen Verlust gelöscht werden dürfen.
Ein kleines Repository kann so aussehen:
class ReportFileRepository(
private val context: Context
) {
fun savePrivateDraft(reportId: String, text: String) {
val file = File(context.filesDir, "draft-$reportId.txt")
file.writeText(text, Charsets.UTF_8)
}
fun readPrivateDraft(reportId: String): String? {
val file = File(context.filesDir, "draft-$reportId.txt")
return if (file.exists()) file.readText(Charsets.UTF_8) else null
}
fun saveTemporaryPreview(reportId: String, bytes: ByteArray): File {
val file = File(context.cacheDir, "preview-$reportId.bin")
file.writeBytes(bytes)
return file
}
}
Der Code zeigt bewusst nur interne Dateien und Cache. Für einen Entwurf ist das passend, weil der Nutzer diese Zwischenfassung nicht direkt im Dateimanager bearbeiten soll. Die Vorschau liegt im Cache, weil sie neu erzeugt werden kann. Genau diese Trennung macht den Unterschied: Nicht jede Datei, die technisch gespeichert werden kann, hat denselben fachlichen Wert.
Wenn du daraus einen Export machen willst, solltest du nicht einfach denselben internen Pfad an eine andere App weiterreichen. Interne Dateien sind privat. Für das Teilen brauchst du einen kontrollierten Weg, zum Beispiel eine vom System verwaltete URI. In vielen Apps nutzt du dafür einen FileProvider oder einen Dokument-Picker-Workflow. Für Medien, die dauerhaft sichtbar sein sollen, ist MediaStore die bessere Richtung.
Typische Stolperfalle
Eine häufige Anfängerentscheidung lautet: „Ich speichere alles extern, dann finde ich es leichter wieder.“ Das klingt praktisch, führt aber zu Problemen. Du erhöhst die Sichtbarkeit von Daten, brauchst eventuell zusätzliche Berechtigungen, musst mit unterschiedlichen Android-Versionen umgehen und vermischst private App-Zustände mit Nutzerdateien. Besonders riskant ist das bei Logs, temporären Exporten oder Dateien mit personenbezogenen Inhalten.
Die andere Seite ist ebenfalls wichtig: Speichere nichts im Cache, was du nicht verlieren darfst. Android kann Cache-Daten löschen. Deine App darf Cache-Daten ebenfalls aufräumen. Wenn ein Nutzer dadurch eine unfertige Arbeit verliert, war der Speicherort falsch gewählt. Prüfe deshalb immer: Kann diese Datei ohne Rückfrage gelöscht und rekonstruiert werden? Wenn nein, gehört sie nicht in cacheDir.
Verbindung zu Offline-First
Bei Offline-First-Apps ist Dateispeicherung oft Teil der Datenstrategie. Eine App kann Serverdaten lokal spiegeln, Anhänge zwischenspeichern oder Medien erst später hochladen. Trotzdem solltest du Dateien nicht als Ersatz für eine klare Datenarchitektur verwenden. Metadaten wie Status, Synchronisationszeitpunkt oder Upload-Fehler gehören meist in eine strukturierte lokale Datenquelle. Die Datei selbst liegt dann an einem passenden Speicherort, während dein Repository den Zusammenhang verwaltet.
So vermeidest du, dass Dateinamen zur versteckten Datenbank werden. Ein Name wie upload_2026_final_new_2.jpg ist kein tragfähiges Modell für Synchronisation. Besser ist eine Tabelle oder ein klarer Datenstatus in deiner Data Layer, der auf eine Datei oder URI verweist. Dadurch kannst du Fehler behandeln, Tests schreiben und später nachvollziehen, warum eine Datei noch nicht hochgeladen wurde.
Prüfung im Alltag
Du kannst dein Verständnis sehr konkret testen. Installiere eine kleine Beispiel-App, speichere eine private Datei in filesDir, eine Vorschau in cacheDir und ein Bild über MediaStore. Prüfe dann mit Debugger und Log-Ausgaben, welcher Codepfad verwendet wird. Deinstalliere die App und beobachte, welche Daten verschwinden. Lösche Cache-Daten und kontrolliere, ob deine App weiterhin korrekt reagiert.
Im Code-Review solltest du bei jeder Datei drei Fragen stellen: Wer soll diese Datei sehen dürfen? Wie lange muss sie leben? Darf sie ohne fachlichen Schaden gelöscht werden? Wenn die Antworten nicht zum gewählten Speicherort passen, ist das ein Designproblem, kein kleiner Implementierungsfehler.
Auch Tests können helfen. Für Repository-Logik kannst du Dateizugriffe über eine kleine Schnittstelle kapseln und mit temporären Verzeichnissen testen. Instrumentation-Tests sind sinnvoll, wenn du Android-spezifische Speicherorte, ContentResolver-Verhalten oder MediaStore-Integration prüfen willst. Du musst nicht jede Plattformdetailsimulation perfekt nachbauen. Wichtig ist, dass deine fachlichen Entscheidungen testbar bleiben.
Fazit
Gute Dateispeicherung beginnt nicht mit der Frage nach dem bequemsten Pfad, sondern mit der Frage nach Privatsphäre, Teilen, Lebensdauer und Wiederherstellbarkeit. Interne Dateien, externe Dateien und Medien lösen unterschiedliche Aufgaben. Wenn du diese Unterschiede sauber in deiner Data Layer kapselst, bleibt deine App verständlicher, sicherer und leichter testbar. Nimm dir als Übung eine bestehende App oder ein Lernprojekt und markiere jede gespeicherte Datei mit ihrem Zweck: privat, Cache, Export oder Medium. Danach prüfst du im Debugger, in Tests oder im Code-Review, ob der tatsächliche Speicherort zu dieser Einordnung passt.