Ketika saya mencoba menerapkan persyaratan yang sangat sederhana — mengunduh gambar dan menyimpannya ke penyimpanan lokal —semuanya tampak baik-baik saja pada awalnya.
- Honor (Android 10) – berfungsi
- Redmi (Android 11) – berfungsi
- Xiaomi (Android 13) – berfungsi
- Samsung (Android 13) – gagal total: dialog izin penyimpanan tidak akan pernah muncul
Kode yang sama, fitur yang sama, tetapi satu perangkat di Android 13 menolak untuk menampilkan perintah izin. Begitulah cara tugas "unduh gambar" kecil ini berubah menjadi pendalaman Penyimpanan Berskala Dan KELOLA_PENYIMPANAN_EKSTERNAL.
Posting ini merangkum bagaimana saya mengadaptasi izin penyimpanan untuk Android 11 dan di atasnya, dan bagaimana saya menangani perilaku yang berbeda-beda di berbagai versi.
1. Bug: Dialog Izin Penyimpanan Tidak Pernah Muncul (Samsung Android 13)
Persyaratannya sederhana:
Unduh gambar dan simpan ke perangkat sehingga muncul di galeri.
Pada tiga perangkat pengujian saya:
- Kehormatan – Android 10 → Oke
- Redmi – Android 11 → Oke
- Xiaomi – Android 13 → Oke
Tapi pada suatu Perangkat Samsung yang menjalankan Android 13, sistem tidak pernah menampilkan dialog izin penyimpanan, tidak peduli bagaimana saya memintanya.



Awalnya saya pikir ini hanya keanehan OEM lainnya, tetapi setelah memeriksa perubahan izin penyimpanan di seluruh versi Android, saya menyadari bahwa saya mengandalkan perilaku yang secara efektif telah ditinggalkan di Android 13 saat menargetkan SDK 33.
2. Akar Masalah: WRITE/READ_EXTERNAL_STORAGE Tidak Digunakan Lagi di Android 13 (SDK 33)
Pada versi Android lama, kita cukup mendeklarasikan dua izin ini dalam manifes:
BACA_PENYIMPANAN_EKSTERNALTULIS_PENYIMPANAN_EKSTERNAL
dan kemudian memintanya pada saat runtime bila diperlukan.
Di Android 13 (SDK 33) dengan targetSdkVersion = 33, pendekatan itu mulai rusak:
TULIS_PENYIMPANAN_EKSTERNALadalah sudah tidak digunakan lagi dan tidak berguna sama sekali pada versi Android terbaru- Jika Anda menambahkan
maxSdkVersion=32untuk izin ini, mereka masih berfungsi di Android 11/12
tapi mereka adalah diabaikan di Android 13 saat menargetkan 33 - Pada saat yang sama, Play Store mengharuskan aplikasi baru untuk menargetkan setidaknya SDK 33
Jadi untuk Android 11+ kita harus beradaptasi dengan:
- Penyimpanan Berskala
- Dan dalam beberapa kasus, izin khusus:
KELOLA_PENYIMPANAN_EKSTERNAL
KELOLA_PENYIMPANAN_EKSTERNAL memberikan akses luas ke semua konten penyimpanan bersama (termasuk file non-media) pada aplikasi. bukan mengizinkan akses ke direktori pribadi aplikasi lain, tetapi masih dianggap sebagai izin yang sangat sensitif oleh Google Play.
Untuk mendukung versi Android yang berbeda, saya akhirnya membagi penanganan izin menjadi:
- Sebelum Android 11 (API < 30) – izin penyimpanan eksternal gaya lama
- Android 11 dan di atasnya – Penyimpanan Berskala + penanganan khusus dengan
KELOLA_PENYIMPANAN_EKSTERNALdi tempat yang benar-benar dibutuhkan
3. Adaptasi Langkah demi Langkah
3.1 Mendeklarasikan MANAGE_EXTERNAL_STORAGE dalam Manifest
Di dalam AndroidManifest.xml:
<uses-permission
android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />⚠️ Catatan: Karena
KELOLA_PENYIMPANAN_EKSTERNALIni adalah izin sensitif, dan dibatasi di Google Play. Saya akan membahas alternatifnya nanti jika Anda hanya ingin menyimpan gambar.
3.2 Periksa Apakah Izin Diberikan
saya sudah menggunakan Izin Mudah untuk menyederhanakan pemeriksaan izin.
private fun checkPer(aktivitas: PreViewActivity): Boolean { kembalikan jika (Build.VERSION.SDK_INT >= 30) { EasyPermissions.hasPermissions( aktivitas, android.Manifest.izin.KELOLA_PENYIMPANAN_EKSTERNAL ) } yang lain { EasyPermissions.hasPermissions( aktivitas, android.Manifest.izin.TULIS_PENYIMPANAN_EKSTERNAL ) } }
- Pada Android 11+ (API >= 30): Saya periksa
KELOLA_PENYIMPANAN_EKSTERNAL - Pada Android 10 dan di bawahnya: Aku masih memeriksa
TULIS_PENYIMPANAN_EKSTERNAL
Perpecahan ini penting karena TULIS_PENYIMPANAN_EKSTERNAL tidak lagi berperilaku seperti pada versi yang lebih baru.
3.3 Meminta Izin Jika Tidak Ada
Jika izin tidak diberikan, saya memintanya secara berbeda berdasarkan versi sistem.
private fun requestStoragePermission(activity: PreViewActivity, curImg: Int) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { // Android 11+ – dialihkan ke halaman pengaturan "Akses semua file" sistem val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION) intent.data = Uri.parse("package:" + activity.packageName) activity.startActivityForResult(intent, 200) } else { // Android 10 dan versi sebelumnya – izin runtime normal val perm = android.Manifest.permission.WRITE_EXTERNAL_STORAGE PaperThreeVariable.isToRequestPer = true EasyPermissions.requestPermissions( PermissionRequest.Builder( activity, 200, perm ).build() ) } }
- Pada Android 11+:Anda tidak bisa begitu saja “memunculkan” dialog runtime normal untuk
KELOLA_PENYIMPANAN_EKSTERNAL
Anda harus mengarahkan pengguna ke halaman pengaturan sistem tempat mereka secara manual memberikan “Akses semua file”. - Pada Android 10 dan di bawahnya:Dialog izin runtime klasik masih berfungsi.
3.4 Menangani Panggilan Balik Izin
EasyPermissions membantu menjembatani panggilan balik Aktivitas dan logika kita sendiri:
mengganti fun onRequestPermissionsResult( requestCode: Int, permissions: Array , grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) } override fun onPermissionsGranted(requestCode: Int, perms: MutableList ) { AppInitUtils().saveFreshAppImageToGallery(ini, curImg) PaperThreeVariable.isToRequestPer = false } override fun onPermissionsDenied(requestCode: Int, perms: MutableList ) { PaperThreeVariable.isToRequestPer = false if (EasyPermissions.somePermissionPermanentlyDenied(ini, izin)) { AppSettingsDialog.Builder(ini) .setRationale("Fungsi ini memerlukan izin penyimpanan untuk diaktifkan") .setNegativeButton("Tidak") .setPositiveButton("Ya") .build() .show() } }
Mengapa saya menggunakan EasyPermissions di sini:
- Pengguna bisa menolak secara permanen izin, yang membuat permintaan berulang gagal secara diam-diam
- EasyPermissions memudahkan untuk:
- Mendeteksi status “ditolak secara permanen”
- Tampilkan dialog yang memandu pengguna ke pengaturan sistem → izin aplikasi untuk mengaktifkan akses penyimpanan secara manual
Setelah izin diberikan, saya memanggil:
AppInitUtils().saveFreshAppImageToGallery(ini, curImg)
untuk benar-benar menyimpan gambar dan menyegarkan galeri.
Setelah adaptasi ini, perangkat Samsung Android 13 akhirnya berperilaku sama seperti yang lain.
Catatan tambahan: Perangkat Xiaomi saya melaporkan Android 13, tetapi "perangkat terhubung historis" di Android Studio mengenalinya sebagai Android 12. Hal itu mungkin menjelaskan mengapa hal itu masih berfungsi dalam beberapa kasus — tetapi inilah mengapa penanganan izin yang sadar versi itu penting.
4. Tentang MANAGE_EXTERNAL_STORAGE dan Pembatasan Google Play
KELOLA_PENYIMPANAN_EKSTERNAL sangat kuat:
Ini memberikan akses baca/tulis ke semua penyimpanan bersama pada perangkat.
Oleh karena itu, Google Play memperlakukannya sebagai izin yang sangat sensitif:
- Ini terutama ditujukan untuk pengelola berkas / cadangan / antivirus aplikasi tipe
- Anda harus menyerahkan pembenaran untuk menggunakannya
- Jika aplikasi Anda hanya merupakan aplikasi konsumen biasa (misalnya, menyimpan gambar, unduhan sederhana), permintaan Anda kemungkinan besar akan ditolak
Jadi jika satu-satunya persyaratan Anda adalah:
“Simpan gambar ke galeri dan buat agar terlihat oleh pengguna.”
maka kamu harus sangat mempertimbangkan untuk menghindari KELOLA_PENYIMPANAN_EKSTERNAL dan sebagai gantinya:
- Menggunakan Toko Media untuk memasukkan gambar ke dalam perpustakaan media sistem
- Atau gunakan API yang dapat menyimpan gambar tanpa memerlukan akses file penuh
Ada beberapa pola untuk:
- Simpan gambar ke direktori Pictures/DCIM
- Beri tahu pemindai media atau andalkan MediaStore agar galeri dapat mengambilnya
- Lakukan semua ini tanpa meminta MANAGE_EXTERNAL_STORAGE
Untuk distribusi internal atau non-Play Store (misalnya, toko aplikasi internal perusahaan), secara teknis Anda masih dapat menggunakan Lingkungan.getExternalStorageDirectory(), tetapi saya tidak menyarankan merancang aplikasi baru dengan dasar ini pada tahun 2025.
5. Ringkasan Versi demi Versi (Android 9 → 13)
Untuk meletakkan semuanya di satu tempat, berikut adalah ringkasan tingkat tinggi tentang bagaimana penyimpanan eksternal dan izin berperilaku di berbagai versi.
Android 9 dan di bawahnya (API 28 dan sebelumnya)
- Izin:
BACA_PENYIMPANAN_EKSTERNALTULIS_PENYIMPANAN_EKSTERNAL
- Perilaku:
- Aplikasi dapat mengakses secara bebas
/kartu sddan subdirektori-nya - File yang dibuat oleh aplikasi tetap ada di perangkat bahkan setelah aplikasi dihapus instalasinya
- Aplikasi dapat mengakses secara bebas
- Pendekatan umum:
- Langsung membaca/menulis di jalur penyimpanan eksternal
Android 10 (API 29) – Penyimpanan Berskala Diperkenalkan
- Izin:
BACA_PENYIMPANAN_EKSTERNALmasih berfungsiTULIS_PENYIMPANAN_EKSTERNALmasih ada, namun cakupan efektifnya berkurang
- Perilaku:
- Penyimpanan Berskala diperkenalkan:
- Aplikasi dibatasi pada direktori khusus aplikasi mereka sendiri di bawah
Android/data/nama.paket.Anda/ - Akses langsung ke file aplikasi lain dibatasi
- Aplikasi dibatasi pada direktori khusus aplikasi mereka sendiri di bawah
- File media (gambar, video, audio) harus diakses melalui Toko Media
requestLegacyExternalStorage=benarbisa mempertahankan perilaku lama untuk sementara
(tetapi bendera ini diabaikan mulai dari Android 11)
- Penyimpanan Berskala diperkenalkan:
- Pendekatan yang direkomendasikan:
- Untuk gambar/video/audio: gunakan Toko Media
- Untuk file pribadi: gunakan
getExternalFilesDir()ataudapatkanDataDir()
Android 11 (API 30) – Penyimpanan Bercakupan Diberlakukan
- Izin:
BACA_PENYIMPANAN_EKSTERNALberfungsi, tetapi hanya untuk media yang dikelola oleh MediaStoreTULIS_PENYIMPANAN_EKSTERNALsecara efektif usang untuk penyimpanan eksternal umumKELOLA_PENYIMPANAN_EKSTERNALdiperkenalkan untuk kasus penggunaan khusus “akses semua file”
- Perilaku:
requestLegacyExternalStorage=benartidak lagi berfungsi; Penyimpanan Berskala adalah selalu aktif- Akses ke
/kartu sd/root diblokir - Aplikasi hanya dapat:
- Mengakses direktori pribadi mereka sendiri
- Akses media bersama melalui Toko Media
- Pendekatan yang direkomendasikan:
- Untuk aplikasi umum:
- Gunakan MediaStore atau SAF (
TINDAKAN_BUKA_DOKUMEN,TINDAKAN_BUAT_DOKUMEN) untuk file yang dipilih pengguna
- Gunakan MediaStore atau SAF (
- Hanya pertimbangkan
KELOLA_PENYIMPANAN_EKSTERNALjika aplikasi Anda benar-benar merupakan pengelola berkas, alat pencadangan, aplikasi keamanan, dll.
- Untuk aplikasi umum:
Android 13 (API 33) – Izin Media Terpisah
- Izin:
BACA_GAMBAR_MEDIA– akses gambarBACA_MEDIA_VIDEO– akses videoBACA_MEDIA_AUDIO– akses audio
- Perilaku:
- Izin media adalah berbutir halus:
- Pengguna hanya dapat memberikan akses gambar, hanya akses video, dan lain-lain.
- Aturan Penyimpanan Berskala dari Android 11 tetap berlaku
- Izin media adalah berbutir halus:
- Pendekatan yang direkomendasikan:
- Minta izin media spesifik yang Anda perlukan:
- Misalnya, jika Anda hanya bekerja dengan gambar, minta saja
BACA_GAMBAR_MEDIA
- Misalnya, jika Anda hanya bekerja dengan gambar, minta saja
- Melakukan bukan meminta
BACA_PENYIMPANAN_EKSTERNALdi Android 13+, karena digantikan oleh izin media baru
- Minta izin media spesifik yang Anda perlukan:
Matriks Cepat (Konseptual)
- Android 9 dan di bawahnya
- Akses ke penyimpanan eksternal luas, dikontrol oleh READ/WRITE_EXTERNAL_STORAGE
- Android 10
- Penyimpanan Berskala diperkenalkan, tetapi ada jalan keluar (
permintaanLegacyExternalStorage)
- Penyimpanan Berskala diperkenalkan, tetapi ada jalan keluar (
- Android 11
- Penyimpanan Bercakupan diberlakukan, sakelar lama dihapus
KELOLA_PENYIMPANAN_EKSTERNALmuncul tetapi sangat terbatas
- Android 13
- Akses media dibagi menjadi
BACA_MEDIA_*izin - Aturan Penyimpanan Bercakupan yang Sama, tetapi kontrol pengguna yang lebih terperinci
- Akses media dibagi menjadi
6. Poin-poin Penting
- Jangan berasumsi bahwa "berfungsi di satu perangkat Android 13" berarti berfungsi di mana saja; OEM dan laporan sistem bisa saja tidak konsisten.
- Untuk Android 11+, pikirkan dalam hal:
- Direktori pribadi aplikasi + MediaStore + SAF, tidak “mentah”
/kartu sdmengakses"”
- Direktori pribadi aplikasi + MediaStore + SAF, tidak “mentah”
- Merawat
KELOLA_PENYIMPANAN_EKSTERNALsebagai pilihan terakhir untuk jenis aplikasi yang sangat spesifik, terutama jika Anda berencana untuk menerbitkannya di Google Play. - Selalu uji pada beberapa perangkat dan versi Android, terutama dalam hal izin dan penyimpanan.
Artikel ini berasal dari proses debugging dan adaptasi saya sendiri dalam proyek Android sungguhan (termasuk perangkat Samsung di Android 13). GPT hanya membantu menerjemahkan dan menyempurnakan kata-katanya; semua konten dan keputusan teknis adalah milik saya.


