Scoped Storage — wat is het, bestandsbeheer en toegang tot opslag

Auteur: IT Sectr Gepubliceerd: 2026-07-10 Leestijd: 10 min

Scoped Storage — is een toegangsmodel tot het bestandssysteem dat is geïntroduceerd in Android 10 (API 29) en de willekeurige toegang van apps tot de gedeelde opslag van het apparaat beperkt. Volgens Google Android Developer Documentation (2024) vervangt Scoped Storage het oude model van READ_EXTERNAL_STORAGE en WRITE_EXTERNAL_STORAGE machtigingen, waarbij apps alleen toegang krijgen tot hun eigen bestanden in een geïsoleerde sandbox en tot gedeelde collecties via MediaStore. Dit model verhoogt de privacy van gebruikersgegevens en voorkomt ongeautoriseerde verzameling van informatie door apps.

Belangrijkste punten

  • Scoped Storage — bestandstoegangsmodel in Android 10+ dat willekeurig lezen van gedeelde opslag beperkt.
  • De app heeft een eigen sandbox met volledige toegang zonder extra machtigingen.
  • Voor toegang tot gedeelde bestanden (foto, video, audio) wordt MediaStore API gebruikt.
  • Voor toegang tot willekeurige mappen en bestanden wordt Storage Access Framework (SAF) gebruikt.
  • De machtigingen READ_EXTERNAL_STORAGE en WRITE_EXTERNAL_STORAGE hebben hun kracht verloren voor de meeste scenario’s.

Wat is Scoped Storage in Android?

Scoped Storage — is een architectonische verandering in Android 10 (API 29) die de manier waarop apps toegang krijgen tot het bestandssysteem van het apparaat fundamenteel verandert. In plaats van volledige toegang tot de gedeelde opslag, krijgt de app alleen toegang tot zijn eigen sandbox en tot bepaalde collecties mediabestanden via MediaStore.

Vóór Scoped Storage kon elke app met de machtiging READ_EXTERNAL_STORAGE alle bestanden in de gedeelde opslag lezen — foto’s, documenten, downloads, gegevens van andere apps. Dit creëerde privacyrisico’s: oneerlijke apps konden informatie over de gebruiker verzamelen zonder diens medeweten.

Volgens Google I/O 2019 beschouwt meer dan 65% van de Android-gebruikers gegevensprivacy als een kritieke factor bij het kiezen van een app. Scoped Storage is het directe antwoord op deze vraag: elke app werkt in een geïsoleerde omgeving en krijgt alleen toegang tot gegevens van anderen met expliciete toestemming van de gebruiker.

Belangrijk: Scoped Storage was in Android 10 optioneel (de app kon het uitschakelen via requestLegacyExternalStorage). Vanaf Android 11 (API 30) is Scoped Storage verplicht geworden voor alle apps, ongeacht de target SDK.

Waarom was Scoped Storage nodig

Google heeft Scoped Storage geïntroduceerd om drie fundamentele problemen van het oude bestandstoegangsmodel op te lossen: privacy, machtigingsbeheer en het opruimen van achtergebleven bestanden.

Het privacyprobleem

In het oude model kon een app met READ_EXTERNAL_STORAGE de hele gedeelde opslag scannen en metadata over de bestanden van de gebruiker verzamelen — geografische coördinaten van foto’s, documentnamen, mapstructuur. Scoped Storage elimineert deze mogelijkheid: zelfs met de machtiging ziet de app alleen bestanden die hij zelf heeft gemaakt en bestanden die de gebruiker expliciet heeft geselecteerd via SAF.

Het opruimprobleem bij verwijdering

Vóór Scoped Storage kon de app bestanden achterlaten in de gedeelde opslag na verwijdering. Na verloop van tijd stapelden rommel-mappen zich op. Scoped Storage lost dit op: alle bestanden in de sandbox van de app worden samen met de app verwijderd, en bestanden via MediaStore hebben een eigenaar en kunnen door het systeem worden opgeruimd.

AspectOud model (Legacy)Scoped Storage
Toegang tot gedeelde opslagVolledig (met machtiging)Alleen eigen sandbox
MediabestandenDirect bestandspadVia MediaStore URI
Andermans bestandenAltijd beschikbaarAlleen via SAF
Opruimen bij verwijderingBestanden blijvenSandbox wordt verwijderd
Controle gebruikerMinimaalExpliciete toestemming per bestand

Scoped Storage maakt deel uit van de algemene strategie van Google om de privacy in Android te versterken, die ook machtigingen “alleen tijdens gebruik”, indicatoren voor toegang tot camera en microfoon en Privacy Dashboard omvat.

Privémap van de app

Elke app in Android krijgt een eigen privémap, toegankelijk via Context.getFilesDir() en context.getCacheDir(). Voor toegang tot de externe (gedeelde) privémap wordt Context.getExternalFilesDir() gebruikt.

In Scoped Storage heeft de app volledige toegang tot zijn eigen externe privémap zonder enige machtigingen. Dit is de primaire locatie voor het opslaan van bestanden die niet toegankelijk mogen zijn voor andere apps of die de app voor eigen gebruik aanmaakt.

kotlin
import android.os.Environment
import java.io.File
import java.io.IOException

class FileManager {

    fun saveToAppStorage(context: Context, fileName: String, data: ByteArray) {
        val appDir = context.getExternalFilesDir(null)
            ?: return
        val file = File(appDir, fileName)
        file.writeBytes(data)
    }

    fun readFromAppStorage(context: Context, fileName: String): ByteArray? {
        val appDir = context.getExternalFilesDir(null)
            ?: return null
        val file = File(appDir, fileName)
        return file.takeIf { it.exists() }?.readBytes()
    }
}

Pad naar de externe privémap: /storage/emulated/0/Android/data/{packageName}/files/. Vanaf Android 11 is het directe bestandspad niet beschikbaar — alleen via API. Dit is een verdere versterking van de beveiliging van Scoped Storage.

MediaStore — toegang tot mediabestanden

MediaStore — is de primaire API voor toegang tot gedeelde mediabestanden (afbeeldingen, video, audio) in Scoped Storage. De app werkt niet met bestandspaden, maar met content URIs die door de MediaStore-provider worden geleverd.

MediaStore is verdeeld in drie hoofdcollecties: Images, Video en Audio. Elke collectie ondersteunt CRUD-bewerkingen via ContentResolver. Voor het invoegen van een nieuw bestand in de Images-collectie wordt MediaStore.Images.Media gebruikt, voor het opvragen van bestaande — query met de betreffende URI.

kotlin
import android.content.ContentValues
import android.provider.MediaStore
import android.os.Environment
import java.io.OutputStream

fun saveImageToGallery(context: Context, bitmap: Bitmap, title: String) {
    val values = ContentValues().apply {
        put(MediaStore.Images.Media.DISPLAY_NAME, "$title.jpg")
        put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
        put(
            MediaStore.Images.Media.RELATIVE_PATH,
            "${Environment.DIRECTORY_PICTURES}/MyApp"
        )
    }

    val uri = context.contentResolver
        .insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
        ?: return

    context.contentResolver.openOutputStream(uri)?.use { output: OutputStream ->
        bitmap.compress(
            Bitmap.CompressFormat.JPEG,
            95,
            output
        )
    }
}

Belangrijk: MediaStore ondersteunt geen willekeurige bestandspaden — alleen content URIs. Een poging om het bestandspad uit een URI te verkrijgen via MediaStore.Files.getContentUri() geeft geen direct pad naar het bestand op Android 11+. Gebruik in plaats daarvan ContentResolver.openInputStream() en openOutputStream() om met de inhoud te werken.

Storage Access Framework (SAF)

Storage Access Framework (SAF) — is de API voor toegang tot willekeurige bestanden en mappen buiten de sandbox van de app. SAF biedt de gebruiker een interface om een bestand of map te selecteren, waarna de app een content URI met tijdelijke toegang ontvangt.

SAF wordt gebruikt voor scenario’s die niet door MediaStore worden gedekt: werken met willekeurige documenten (PDF, ZIP, APK), toegang tot mappen op de SD-kaart, importeren en exporteren van bestanden uit andere apps. De gebruiker selecteert het bestand expliciet via de systeembrede bestandsselectie — dit garandeert zijn toestemming voor toegang.

kotlin
import android.app.Activity
import android.content.Intent
import android.net.Uri
import android.provider.DocumentsContract

const val REQUEST_CODE_PICK_DIR = 1001

fun pickDirectory(activity: Activity) {
    val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
    activity.startActivityForResult(intent, REQUEST_CODE_PICK_DIR)
}

fun handlePickResult(requestCode: Int, data: Intent?) {
    if (requestCode == REQUEST_CODE_PICK_DIR && data != null) {
        val treeUri: Uri = data.data ?: return

        // Verkrijg permanente URI-toestemming
        val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or
                       Intent.FLAG_GRANT_WRITE_URI_PERMISSION
        contentResolver.takePersistableUriPermission(treeUri, flags)
    }
}

SAF geeft de app toegang tot de door de gebruiker geselecteerde map tot het apparaat opnieuw wordt opgestart (bij gebruik van takePersistableUriPermission). Dit is de enige manier om toegang te krijgen tot willekeurige bestanden in de gedeelde opslag op Android 11+.

Migratie van de app naar Scoped Storage

Migratie van een bestaande Android-app naar Scoped Storage vereist wijzigingen in verschillende belangrijke gebieden. Google beveelt een gefaseerde aanpak aan met testen op Android 11+.

Vervangen van bestandspaden door content URIs

Vervang alle directe File-bewerkingen in de gedeelde opslag door ContentResolver.openInputStream / openOutputStream. Voor bestanden in de sandbox van de app (getExternalFilesDir) blijven bestandspaden werken.

AndroidManifest bijwerken

Verwijder READ_EXTERNAL_STORAGE en WRITE_EXTERNAL_STORAGE als ze niet nodig zijn voor specifieke scenario’s (bijvoorbeeld bestandsbeheer — daarvoor is er de speciale machtiging MANAGE_EXTERNAL_STORAGE).

ScenarioOude aanpakScoped Storage aanpak
Opslaan fotoFile(path).writeBytes()MediaStore + ContentResolver
Lezen PDFFile(path).inputStream()SAF ACTION_OPEN_DOCUMENT
Eigen bestandenEnvironment.getExternalStorageDirectory()context.getExternalFilesDir()
CacheFile(cacheDir).writeBytes()context.cacheDir (ongewijzigd)

Test de app na migratie op Android 11+ (API 30) met targetSdk = 30 of hoger in build.gradle. Zorg ervoor dat alle bestandsbewerkingen in de gedeelde opslag via MediaStore of SAF werken, niet via directe bestandspaden.

kotlin
import android.os.Build

fun isScopedStorage(): Boolean {
    return Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
}

fun compatReadFile(context: Context, uri: Uri): ByteArray? {
    return if (isScopedStorage()) {
        context.contentResolver
            .openInputStream(uri)?.readBytes()
    } else {
        File(uri.path ?: return null)
            .takeIf { it.exists() }
            ?.readBytes()
    }
}

Volgens Google Play Console (2024) draait meer dan 78% van de actieve Android-apparaten op Android 10+ met Scoped Storage. Migratie is een verplichte stap voor het publiceren van updates in Google Play: nieuwe apps moeten API 31+ targeten, updates — API 30+.

Veelgestelde vragen

Kan ik Scoped Storage uitschakelen in Android 11?

Nee, vanaf Android 11 (API 30) is Scoped Storage verplicht voor alle apps. De vlag requestLegacyExternalStorage, beschikbaar in Android 10, werkt niet op API 30+. De enige manier om brede toegang tot het bestandssysteem te krijgen is de machtiging MANAGE_EXTERNAL_STORAGE, maar deze is alleen bedoeld voor bestandsbeheerders en antivirusprogramma’s.

Wat is MANAGE_EXTERNAL_STORAGE en hoe krijg ik het?

MANAGE_EXTERNAL_STORAGE — een speciale machtiging voor apps die volledige toegang tot het bestandssysteem nodig hebben (bestandsbeheerders, back-up tools). Het aanvragen van de machtiging opent een systeemscherm met een waarschuwing voor de gebruiker. Bij publicatie in Google Play moet het Declaration-formulier over de noodzaak van deze machtiging worden ingevuld.

Hoe krijg ik een bestandspad uit een content URI in Scoped Storage?

In Scoped Storage op Android 11+ kan geen direct bestandspad uit een content URI worden verkregen. Gebruik in plaats daarvan ContentResolver.openInputStream() voor lezen en openOutputStream() voor schrijven. Als je een bestandspad nodig hebt voor compatibiliteit met een externe bibliotheek — maak een kopie van het bestand in getCacheDir() en werk met de kopie.

Hoe beïnvloedt Scoped Storage FileProvider?

FileProvider blijft ongewijzigd werken — het wordt gebruikt om toegang te bieden tot bestanden uit de sandbox van de app aan andere apps via content URIs. Scoped Storage heeft geen invloed op FileProvider, omdat FileProvider werkt op het niveau van content URIs, niet van directe bestandspaden.

Hoe controleer ik of het apparaat Scoped Storage ondersteunt?

Controleer Build.VERSION.SDK_INT: als >= Build.VERSION_CODES.Q (29) is, ondersteunt het apparaat Scoped Storage. Op Android 10 kan Scoped Storage echter worden uitgeschakeld via requestLegacyExternalStorage. Op Android 11+ controleer of de vlag requestLegacyExternalStorage in het manifest is ingesteld — zo niet, dan is Scoped Storage actief.

Samenvatting

  • Scoped Storage — bestandstoegangsmodel in Android 10+ dat willekeurig lezen van gedeelde opslag beperkt.
  • De app heeft volledige toegang tot zijn eigen privésandbox zonder extra machtigingen.
  • Voor toegang tot gedeelde mediabestanden wordt MediaStore API met content URIs gebruikt.
  • Voor toegang tot willekeurige bestanden en mappen wordt Storage Access Framework (SAF) gebruikt.
  • Vanaf Android 11 is Scoped Storage verplicht voor alle apps.
  • De machtigingen READ_EXTERNAL_STORAGE en WRITE_EXTERNAL_STORAGE werken niet in de meeste scenario’s op Android 11+.
  • Bij migratie vervang je directe bestandspaden door ContentResolver.openInputStream / openOutputStream.

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook