Scoped Storage — ano ito, pamamahala ng file at access sa storage

May-akda: IT Sectr Nai-publish: 2026-07-10 Oras ng pagbabasa: 10 min

Scoped Storage — ay isang modelo ng access sa file system na ipinakilala sa Android 10 (API 29) na naglilimita sa arbitraryong access ng mga app sa shared storage ng device. Ayon sa Google Android Developer Documentation (2024), pinapalitan ng Scoped Storage ang lumang modelo ng mga pahintulot na READ_EXTERNAL_STORAGE at WRITE_EXTERNAL_STORAGE, na nagbibigay sa mga app ng access lamang sa kanilang sariling mga file sa isang isolated na sandbox at sa mga shared collection sa pamamagitan ng MediaStore. Ang modelong ito ay nagpapataas ng privacy ng data ng user at pumipigil sa hindi awtorisadong pangongolekta ng impormasyon ng mga app.

Mga Pangunahing Punto

  • Scoped Storage — modelo ng access sa file sa Android 10+ na naglilimita sa arbitraryong pagbasa ng shared storage.
  • Ang app ay may sariling sandbox na may buong access nang walang karagdagang pahintulot.
  • Para sa access sa shared files (photo, video, audio) ginagamit ang MediaStore API.
  • Para sa access sa arbitraryong direktoryo at file ginagamit ang Storage Access Framework (SAF).
  • Ang mga pahintulot na READ_EXTERNAL_STORAGE at WRITE_EXTERNAL_STORAGE ay nawalan ng bisa para sa karamihan ng mga senaryo.

Ano ang Scoped Storage sa Android?

Scoped Storage — ay isang pagbabago sa arkitektura sa Android 10 (API 29) na pangunahing nagbabago sa paraan ng pag-access ng mga app sa file system ng device. Sa halip na buong access sa shared storage, ang app ay nakakakuha ng access lamang sa sarili nitong sandbox at sa ilang mga koleksyon ng media file sa pamamagitan ng MediaStore.

Bago ang Scoped Storage, sinumang app na may pahintulot na READ_EXTERNAL_STORAGE ay maaaring magbasa ng lahat ng file sa shared storage — mga larawan, dokumento, download, data ng iba pang app. Ito ay lumikha ng mga panganib sa privacy: ang mga hindi tapat na app ay maaaring mangolekta ng impormasyon tungkol sa user nang hindi nito nalalaman.

Ayon sa Google I/O 2019, higit sa 65% ng mga gumagamit ng Android ay itinuturing ang privacy ng data bilang kritikal na kadahilanan sa pagpili ng app. Ang Scoped Storage ay direktang tugon sa kahilingang ito: bawat app ay gumagana sa isang isolated na kapaligiran at nakakakuha ng access sa data ng iba lamang sa malinaw na pahintulot ng user.

Mahalaga: Ang Scoped Storage sa Android 10 ay opsyonal (maaaring i-disable ito ng app sa pamamagitan ng requestLegacyExternalStorage). Simula sa Android 11 (API 30), ang Scoped Storage ay naging mandatory para sa lahat ng app, anuman ang target SDK.

Bakit kailangan ang Scoped Storage

Google ay nagpakilala ng Scoped Storage upang malutas ang tatlong pangunahing problema ng lumang modelo ng access sa file: privacy, pamamahala ng pahintulot, at paglilinis ng natitirang file.

Problema sa privacy

Sa lumang modelo, ang isang app na may READ_EXTERNAL_STORAGE ay maaaring mag-scan ng buong shared storage at mangolekta ng metadata tungkol sa mga file ng user — mga geographic na coordinate ng mga larawan, pangalan ng dokumento, istraktura ng direktoryo. Inaalis ng Scoped Storage ang posibilidad na ito: kahit na may pahintulot, ang app ay nakikita lamang ang mga file na nilikha nito mismo at ang mga file na malinaw na pinili ng user sa pamamagitan ng SAF.

Problema sa paglilinis kapag nag-alis ng app

Bago ang Scoped Storage, ang app ay maaaring mag-iwan ng mga file sa shared storage pagkatapos alisin. Sa paglipas ng panahon, ang mga basurang direktoryo ay naipon. Nilulutas ito ng Scoped Storage: lahat ng file sa sandbox ng app ay tinatanggal kasama ng app, at ang mga file sa pamamagitan ng MediaStore ay may may-ari at maaaring linisin ng system.

AspektoLumang modelo (Legacy)Scoped Storage
Access sa shared storageBuong (may pahintulot)Sariling sandbox lamang
Media fileDirektang file pathSa pamamagitan ng MediaStore URI
File ng ibaLaging availableSa pamamagitan lamang ng SAF
Paglilinis sa pag-alisNananatili ang fileTinatanggal ang sandbox
Kontrol ng userMinimalMalinaw na pahintulot bawat file

Ang Scoped Storage ay bahagi ng pangkalahatang estratehiya ng Google para palakasin ang privacy sa Android, na kasama rin ang mga pahintulot na “sa oras lamang ng paggamit”, mga indicator ng access sa camera at mikropono, at Privacy Dashboard.

Pribadong direktoryo ng app

Bawat app sa Android ay nakakakuha ng sarili nitong pribadong direktoryo, naa-access sa pamamagitan ng Context.getFilesDir() at context.getCacheDir(). Para sa access sa panlabas (shared) na pribadong direktoryo, ginagamit ang Context.getExternalFilesDir().

Sa Scoped Storage, ang app ay may buong access sa sarili nitong panlabas na pribadong direktoryo nang walang anumang pahintulot. Ito ang pangunahing lugar para sa pag-iimbak ng mga file na hindi dapat ma-access ng iba pang app o na nilikha ng app para sa sarili nitong paggamit.

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

Path sa panlabas na pribadong direktoryo: /storage/emulated/0/Android/data/{packageName}/files/. Simula sa Android 11, ang direktang file path ay hindi available — sa pamamagitan lamang ng API. Ito ay isa pang pagpapalakas ng seguridad ng Scoped Storage.

MediaStore — access sa media file

MediaStore — ay ang pangunahing API para sa access sa shared media file (mga larawan, video, audio) sa Scoped Storage. Ang app ay hindi gumagana sa mga file path, kundi sa mga content URIs na ibinigay ng MediaStore provider.

Ang MediaStore ay nahahati sa tatlong pangunahing koleksyon: Images, Video at Audio. Bawat koleksyon ay sumusuporta sa CRUD operations sa pamamagitan ng ContentResolver. Para sa pagpasok ng bagong file sa Images collection, ginagamit ang MediaStore.Images.Media, para sa pag-query ng mga umiiral na — query na may kaukulang 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
        )
    }
}

Mahalaga: Hindi sinusuportahan ng MediaStore ang arbitraryong file path — content URIs lamang. Ang pagtatangkang kumuha ng file path mula sa URI sa pamamagitan ng MediaStore.Files.getContentUri() ay hindi magbibigay ng direktang path sa file sa Android 11+. Sa halip, gamitin ang ContentResolver.openInputStream() at openOutputStream() para sa pagtatrabaho sa nilalaman.

Storage Access Framework (SAF)

Storage Access Framework (SAF) — ay ang API para sa access sa arbitraryong file at direktoryo sa labas ng sandbox ng app. Ang SAF ay nagbibigay sa user ng interface para pumili ng file o direktoryo, pagkatapos nito ang app ay makakatanggap ng content URI na may pansamantalang access.

Ang SAF ay ginagamit para sa mga senaryo na hindi saklaw ng MediaStore: pagtatrabaho sa arbitraryong dokumento (PDF, ZIP, APK), access sa mga direktoryo sa SD card, pag-import at pag-export ng file mula sa iba pang app. Ang user ay malinaw na pumipili ng file sa pamamagitan ng system file picker — ginagarantiyahan nito ang kanyang pahintulot para sa access.

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

        // Kumuha ng persistent URI permission
        val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or
                       Intent.FLAG_GRANT_WRITE_URI_PERMISSION
        contentResolver.takePersistableUriPermission(treeUri, flags)
    }
}

Ang SAF ay nagbibigay sa app ng access sa direktoryo na pinili ng user hanggang sa i-restart ang device (kapag ginagamit ang takePersistableUriPermission). Ito ang tanging paraan upang makakuha ng access sa arbitraryong file sa shared storage sa Android 11+.

Pag-migrate ng app sa Scoped Storage

Ang pag-migrate ng umiiral na Android app sa Scoped Storage ay nangangailangan ng mga pagbabago sa ilang pangunahing lugar. Inirerekomenda ng Google ang isang phased approach na may pagsubok sa Android 11+.

Pagpapalit ng file path ng content URIs

Palitan ang lahat ng direktang File operations sa shared storage ng ContentResolver.openInputStream / openOutputStream. Para sa mga file sa sandbox ng app (getExternalFilesDir), patuloy na gumagana ang mga file path.

Pag-update ng AndroidManifest

Alisin ang READ_EXTERNAL_STORAGE at WRITE_EXTERNAL_STORAGE kung hindi kailangan para sa mga tiyak na senaryo (halimbawa, pamamahala ng file — para doon ay may espesyal na pahintulot na MANAGE_EXTERNAL_STORAGE).

SenaryoLumang approachScoped Storage approach
Pag-save ng larawanFile(path).writeBytes()MediaStore + ContentResolver
Pagbasa ng PDFFile(path).inputStream()SAF ACTION_OPEN_DOCUMENT
Sariling fileEnvironment.getExternalStorageDirectory()context.getExternalFilesDir()
CacheFile(cacheDir).writeBytes()context.cacheDir (walang pagbabago)

Pagkatapos ng migrate, subukan ang app sa Android 11+ (API 30) na may targetSdk = 30 o mas mataas sa build.gradle. Tiyakin na ang lahat ng file operations sa shared storage ay gumagana sa pamamagitan ng MediaStore o SAF, hindi sa pamamagitan ng direktang file path.

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

Ayon sa Google Play Console (2024), higit sa 78% ng mga aktibong Android device ay tumatakbo sa Android 10+ na may Scoped Storage. Ang pag-migrate ay isang mandatoryong hakbang para sa pag-publish ng mga update sa Google Play: ang mga bagong app ay dapat mag-target ng API 31+, mga update — API 30+.

Mga Madalas Itanong

Maaari bang i-disable ang Scoped Storage sa Android 11?

Hindi, simula sa Android 11 (API 30) ang Scoped Storage ay mandatory para sa lahat ng app. Ang flag na requestLegacyExternalStorage, na available sa Android 10, ay hindi gumagana sa API 30+. Ang tanging paraan upang makakuha ng malawakang access sa file system ay ang pahintulot na MANAGE_EXTERNAL_STORAGE, ngunit ito ay para lamang sa mga file manager at antivirus.

Ano ang MANAGE_EXTERNAL_STORAGE at paano ito makuha?

MANAGE_EXTERNAL_STORAGE — isang espesyal na pahintulot para sa mga app na nangangailangan ng buong access sa file system (mga file manager, backup tool). Ang kahilingan ng pahintulot ay nagbubukas ng system screen na may babala para sa user. Kapag nag-publish sa Google Play, kinakailangang punan ang Declaration form tungkol sa pangangailangan ng pahintulot na ito.

Paano makakuha ng file path mula sa content URI sa Scoped Storage?

Sa Scoped Storage sa Android 11+, ang direktang file path mula sa content URI ay hindi maaaring makuha. Sa halip, gamitin ang ContentResolver.openInputStream() para sa pagbasa at openOutputStream() para sa pagsulat. Kung kailangan mo ng file path para sa compatibility sa third-party na library — gumawa ng kopya ng file sa getCacheDir() at magtrabaho sa kopya.

Paano nakakaapekto ang Scoped Storage sa FileProvider?

FileProvider ay patuloy na gumagana nang walang pagbabago — ginagamit ito upang magbigay ng access sa mga file mula sa sandbox ng app sa iba pang app sa pamamagitan ng content URIs. Hindi naaapektuhan ng Scoped Storage ang FileProvider, dahil ang FileProvider ay gumagana sa antas ng content URIs, hindi sa direktang file path.

Paano suriin kung sinusuportahan ng device ang Scoped Storage?

Suriin ang Build.VERSION.SDK_INT: kung >= Build.VERSION_CODES.Q (29), sinusuportahan ng device ang Scoped Storage. Gayunpaman, sa Android 10, ang Scoped Storage ay maaaring i-disable sa pamamagitan ng requestLegacyExternalStorage. Sa Android 11+, suriin kung ang flag na requestLegacyExternalStorage ay nakatakda sa manifest — kung hindi, ang Scoped Storage ay aktibo.

Buod

  • Scoped Storage — modelo ng access sa file sa Android 10+ na naglilimita sa arbitraryong pagbasa ng shared storage.
  • Ang app ay may buong access sa sarili nitong pribadong sandbox nang walang karagdagang pahintulot.
  • Para sa access sa shared media file ginagamit ang MediaStore API na may content URIs.
  • Para sa access sa arbitraryong file at direktoryo ginagamit ang Storage Access Framework (SAF).
  • Simula sa Android 11, ang Scoped Storage ay mandatory para sa lahat ng app.
  • Ang mga pahintulot na READ_EXTERNAL_STORAGE at WRITE_EXTERNAL_STORAGE ay hindi gumagana sa karamihan ng senaryo sa Android 11+.
  • Sa pag-migrate, palitan ang direktang file path ng ContentResolver.openInputStream / openOutputStream.

Gagawa kami ng mobile application na turnkey

Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.

Pag-usapan ang proyekto

Basahin din