Scoped Storage — vad det är, filhantering och åtkomst till lagring

Författare: IT Sectr Publicerad: 2026-07-10 Lästid: 10 min

Scoped Storage — är en åtkomstmodell till filsystemet som introducerades i Android 10 (API 29) och begränsar appars godtyckliga åtkomst till enhetens delade lagring. Enligt Google Android Developer Documentation (2024) ersätter Scoped Storage den gamla modellen med READ_EXTERNAL_STORAGE och WRITE_EXTERNAL_STORAGE-behörigheter, och ger appar åtkomst endast till deras egna filer i en isolerad sandlåda och till delade samlingar via MediaStore. Denna modell ökar integriteten för användardata och förhindrar obehörig insamling av information från appar.

Huvudpunkter

  • Scoped Storage — filåtkomstmodell i Android 10+ som begränsar godtycklig läsning av delad lagring.
  • Appen har en egen sandlåda med full åtkomst utan ytterligare behörigheter.
  • För åtkomst till delade filer (foto, video, ljud) används MediaStore API.
  • För åtkomst till godtyckliga kataloger och filer används Storage Access Framework (SAF).
  • Behörigheterna READ_EXTERNAL_STORAGE och WRITE_EXTERNAL_STORAGE har förlorat sin kraft för de flesta scenarier.

Vad är Scoped Storage i Android?

Scoped Storage — är en arkitektonisk förändring i Android 10 (API 29) som fundamentalt ändrar hur appar får åtkomst till enhetens filsystem. Istället för full åtkomst till den delade lagringen får appen endast åtkomst till sin egen sandlåda och till vissa samlingar av mediafiler via MediaStore.

Före Scoped Storage kunde alla appar med behörigheten READ_EXTERNAL_STORAGE läsa alla filer i den delade lagringen — foton, dokument, nedladdningar, data från andra appar. Detta skapade integritetsrisker: oärliga appar kunde samla in information om användaren utan dennes vetskap.

Enligt Google I/O 2019 anser mer än 65% av Android-användare att dataintegritet är en kritisk faktor vid val av app. Scoped Storage är ett direkt svar på denna efterfrågan: varje app arbetar i en isolerad miljö och får åtkomst till andras data endast med användarens uttryckliga samtycke.

Viktigt: Scoped Storage var valfritt i Android 10 (appen kunde inaktivera det via requestLegacyExternalStorage). Från och med Android 11 (API 30) blev Scoped Storage obligatoriskt för alla appar, oavsett target SDK.

Varför behövdes Scoped Storage

Google introducerade Scoped Storage för att lösa tre grundläggande problem med den gamla filåtkomstmodellen: integritet, behörighetshantering och rensning av kvarvarande filer.

Integritetsproblemet

I den gamla modellen kunde en app med READ_EXTERNAL_STORAGE skanna hela den delade lagringen och samla in metadata om användarens filer — geografiska koordinater för foton, dokumentnamn, katalogstruktur. Scoped Storage eliminerar denna möjlighet: även med behörigheten ser appen bara filer som den själv har skapat och filer som användaren uttryckligen har valt via SAF.

Rensningsproblemet vid borttagning av app

Före Scoped Storage kunde appen lämna kvar filer i den delade lagringen efter borttagning. Med tiden samlades skräp-kataloger på hög. Scoped Storage löser detta: alla filer i appens sandlåda raderas tillsammans med appen, och filer via MediaStore har en ägare och kan rensas av systemet.

AspektGammal modell (Legacy)Scoped Storage
Åtkomst till delad lagringFull (med behörighet)Endast egen sandlåda
MediafilerDirekt filsökvägVia MediaStore URI
Andras filerAlltid tillgängligaEndast via SAF
Rensning vid borttagningFiler blir kvarSandlådan raderas
Kontroll av användareMinimalUttryckligt samtycke per fil

Scoped Storage är en del av Googles övergripande strategi för att stärka integriteten i Android, som också inkluderar ”endast under användning”-behörigheter, indikatorer för kamera- och mikrofonåtkomst samt Privacy Dashboard.

Appens privata katalog

Varje app i Android får en egen privat katalog, tillgänglig via Context.getFilesDir() och context.getCacheDir(). För åtkomst till den externa (delade) privata katalogen används Context.getExternalFilesDir().

I Scoped Storage har appen full åtkomst till sin externa privata katalog utan några behörigheter. Detta är den primära platsen för att lagra filer som inte ska vara tillgängliga för andra appar eller som appen skapar för eget bruk.

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

Sökväg till den externa privata katalogen: /storage/emulated/0/Android/data/{packageName}/files/. Från och med Android 11 är direkt filsökväg inte tillgänglig — endast via API. Detta är ytterligare en förstärkning av Scoped Storages säkerhet.

MediaStore — åtkomst till mediafiler

MediaStore — är det primära API:t för åtkomst till delade mediafiler (bilder, video, ljud) i Scoped Storage. Appen arbetar inte med filsökvägar, utan med content URIs som tillhandahålls av MediaStore-leverantören.

MediaStore är uppdelat i tre huvudsamlingar: Images, Video och Audio. Varje samling stöder CRUD-operationer via ContentResolver. För att infoga en ny fil i Images-samlingen används MediaStore.Images.Media, för att fråga efter befintliga — query med motsvarande 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
        )
    }
}

Viktigt: MediaStore stöder inte godtyckliga filsökvägar — endast content URIs. Ett försök att få filsökvägen från en URI via MediaStore.Files.getContentUri() ger inte en direkt sökväg till filen på Android 11+. Använd istället ContentResolver.openInputStream() och openOutputStream() för att arbeta med innehållet.

Storage Access Framework (SAF)

Storage Access Framework (SAF) — är API:t för åtkomst till godtyckliga filer och kataloger utanför appens sandlåda. SAF ger användaren ett gränssnitt för att välja en fil eller katalog, varefter appen får en content URI med temporär åtkomst.

SAF används för scenarier som inte täcks av MediaStore: arbete med godtyckliga dokument (PDF, ZIP, APK), åtkomst till kataloger på SD-kortet, import och export av filer från andra appar. Användaren väljer uttryckligen filen via systemets filväljare — detta garanterar dennes samtycke till åtkomst.

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

        // Få permanent URI-behörighet
        val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or
                       Intent.FLAG_GRANT_WRITE_URI_PERMISSION
        contentResolver.takePersistableUriPermission(treeUri, flags)
    }
}

SAF ger appen åtkomst till den av användaren valda katalogen tills enheten startas om (när takePersistableUriPermission används). Detta är det enda sättet att få åtkomst till godtyckliga filer i den delade lagringen på Android 11+.

Migrera appen till Scoped Storage

Migrering av en befintlig Android-app till Scoped Storage kräver ändringar inom flera viktiga områden. Google rekommenderar en stegvis metod med testning på Android 11+.

Ersätta filsökvägar med content URIs

Ersätt alla direkta File-operationer i den delade lagringen med ContentResolver.openInputStream / openOutputStream. För filer i appens sandlåda (getExternalFilesDir) fortsätter filsökvägar att fungera.

Uppdatera AndroidManifest

Ta bort READ_EXTERNAL_STORAGE och WRITE_EXTERNAL_STORAGE om de inte behövs för specifika scenarier (t.ex. filhantering — för det finns den särskilda behörigheten MANAGE_EXTERNAL_STORAGE).

ScenarioGammal metodScoped Storage-metod
Spara fotoFile(path).writeBytes()MediaStore + ContentResolver
Läsa PDFFile(path).inputStream()SAF ACTION_OPEN_DOCUMENT
Egna filerEnvironment.getExternalStorageDirectory()context.getExternalFilesDir()
CacheFile(cacheDir).writeBytes()context.cacheDir (oförändrat)

Efter migreringen, testa appen på Android 11+ (API 30) med targetSdk = 30 eller högre i build.gradle. Se till att alla filoperationer i den delade lagringen fungerar via MediaStore eller SAF, inte via direkta filsökvägar.

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

Enligt Google Play Console (2024) kör mer än 78% av aktiva Android-enheter Android 10+ med Scoped Storage. Migrering är ett obligatoriskt steg för att publicera uppdateringar i Google Play: nya appar måste rikta sig till API 31+, uppdateringar — API 30+.

Vanliga frågor

Kan jag inaktivera Scoped Storage i Android 11?

Nej, från Android 11 (API 30) är Scoped Storage obligatoriskt för alla appar. Flaggan requestLegacyExternalStorage, som fanns i Android 10, fungerar inte på API 30+. Det enda sättet att få bred åtkomst till filsystemet är behörigheten MANAGE_EXTERNAL_STORAGE, men den är endast avsedd för filhanterare och antivirusprogram.

Vad är MANAGE_EXTERNAL_STORAGE och hur får jag det?

MANAGE_EXTERNAL_STORAGE — en särskild behörighet för appar som behöver full åtkomst till filsystemet (filhanterare, backup-verktyg). Begäran om behörigheten öppnar en systemskärm med en varning för användaren. Vid publicering i Google Play måste Declaration-formuläret om nödvändigheten av denna behörighet fyllas i.

Hur får jag filsökvägen från en content URI i Scoped Storage?

I Scoped Storage på Android 11+ kan en direkt filsökväg från en content URI inte erhållas. Använd istället ContentResolver.openInputStream() för läsning och openOutputStream() för skrivning. Om du behöver filsökvägen för kompatibilitet med ett tredjepartsbibliotek — skapa en kopia av filen i getCacheDir() och arbeta med kopian.

Hur påverkar Scoped Storage FileProvider?

FileProvider fortsätter att fungera oförändrat — det används för att ge åtkomst till filer från appens sandlåda till andra appar via content URIs. Scoped Storage påverkar inte FileProvider, eftersom FileProvider arbetar på nivån av content URIs, inte direkta filsökvägar.

Hur kontrollerar jag om enheten stöder Scoped Storage?

Kontrollera Build.VERSION.SDK_INT: om >= Build.VERSION_CODES.Q (29) stöder enheten Scoped Storage. På Android 10 kan Scoped Storage dock inaktiveras via requestLegacyExternalStorage. På Android 11+, kontrollera om flaggan requestLegacyExternalStorage är inställd i manifestet — om inte, är Scoped Storage aktivt.

Sammanfattning

  • Scoped Storage — filåtkomstmodell i Android 10+ som begränsar godtycklig läsning av delad lagring.
  • Appen har full åtkomst till sin privata sandlåda utan ytterligare behörigheter.
  • För åtkomst till delade mediafiler används MediaStore API med content URIs.
  • För åtkomst till godtyckliga filer och kataloger används Storage Access Framework (SAF).
  • Från och med Android 11 är Scoped Storage obligatoriskt för alla appar.
  • Behörigheterna READ_EXTERNAL_STORAGE och WRITE_EXTERNAL_STORAGE fungerar inte i de flesta scenarier på Android 11+.
  • Vid migrering, ersätt direkta filsökvägar med ContentResolver.openInputStream / openOutputStream.

Vi utvecklar en mobil applikation nyckelfärdigt

IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.

Diskutera projektet

Läs också