With the release of Android 10 and above, Google introduced Scoped Storage as a new way to handle files and protect user privacy.
However, many developers face issues when Kotlin Scoped Storage is not working on Android 11+.
This article will explain why these problems occur, common mistakes, and how to properly implement file access using Scoped Storage with complete Kotlin code examples.

What is Scoped Storage?
Scoped Storage is a security feature that limits how apps can access files on the device’s shared storage.
Instead of allowing direct access to the entire storage, Android forces apps to store and manage files in specific app-related directories such as:
/Android/data/<package_name>/files/
/Android/media/<package_name>/
This protects user privacy but also causes compatibility issues for developers who are migrating from older storage methods.
Why Scoped Storage Not Working on Android 11+
There are several reasons why Scoped Storage may fail:
- Incorrect Permissions: You must request
READ_EXTERNAL_STORAGE
andWRITE_EXTERNAL_STORAGE
in Android 10.
On Android 11+, you often needMANAGE_EXTERNAL_STORAGE
. - Legacy Flag Deprecated: The
requestLegacyExternalStorage="true"
flag no longer works on Android 11+. - Wrong Directory Access: Apps cannot freely write files outside their scoped directory.
- Missing MediaStore API: For media files (images, videos, audio), you must use
MediaStore
.
How to Fix Scoped Storage Issues
Below is a Kotlin example showing how to properly save and read files using Scoped Storage on Android 11+.
We will create a text file inside the app’s private folder and also insert an image into MediaStore
.
Example 1: Writing a File in App-Specific Storage
// Save a file inside app-specific directory fun saveTextFile(context: Context, fileName: String, content: String) { val file = File(context.getExternalFilesDir(null), fileName) file.writeText(content) } // Read file from app-specific directory fun readTextFile(context: Context, fileName: String): String? { val file = File(context.getExternalFilesDir(null), fileName) return if (file.exists()) file.readText() else null }
This approach works without requiring dangerous permissions since it uses the app’s private storage.
Example 2: Saving Image with MediaStore on Android 11+
@SuppressLint("InlinedApi") fun saveImageToMediaStore(context: Context, bitmap: Bitmap, fileName: String) { val values = ContentValues().apply { put(MediaStore.Images.Media.DISPLAY_NAME, "$fileName.jpg") put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg") put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/MyAppImages") put(MediaStore.Images.Media.IS_PENDING, 1) } val resolver = context.contentResolver val uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values) uri?.let { resolver.openOutputStream(it).use { outStream -> bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outStream) } values.clear() values.put(MediaStore.Images.Media.IS_PENDING, 0) resolver.update(it, values, null, null) } }
This code saves an image in the Pictures/MyAppImages folder using the MediaStore
API, which is the recommended method on Android 11+.
Common Mistakes Developers Make
- Using
Environment.getExternalStorageDirectory()
(deprecated and blocked). - Forgetting to declare
android:requestLegacyExternalStorage="true"
for Android 10 apps (though it won’t work on Android 11). - Not handling runtime permissions properly.
- Expecting old
File API
methods to still work.
Scoped Storage vs Legacy Storage
Here is a quick comparison:
Feature | Legacy Storage | Scoped Storage |
---|---|---|
File Access | Full external storage | App-specific + MediaStore |
Privacy | Low | High |
Compatibility | Works up to Android 9 | Required from Android 10+ |
Best Practices for Kotlin Scoped Storage
- Use
MediaStore
for images, videos, and audio files. - Use
getExternalFilesDir()
for private app storage. - Avoid deprecated APIs like
Environment.getExternalStorageDirectory()
. - Request permissions dynamically when necessary.
Conclusion
If you face Kotlin Scoped Storage not working on Android 11+, the issue is usually related to permissions, deprecated APIs, or misuse of file paths.
By following best practices and using MediaStore
and app-specific directories, your app will work seamlessly across modern Android versions.
For more details, you can check the official Android Storage Documentation.