free geoip
33

Kotlin Scoped Storage Not Working on Android 11+

With the release of Android 10 and above, Google introduced Scoped Storage as a new way to handle files and…

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.

Kotlin Scoped Storage Not Working on Android 11+

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:

  1. Incorrect Permissions: You must request READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE in Android 10.
    On Android 11+, you often need MANAGE_EXTERNAL_STORAGE.
  2. Legacy Flag Deprecated: The requestLegacyExternalStorage="true" flag no longer works on Android 11+.
  3. Wrong Directory Access: Apps cannot freely write files outside their scoped directory.
  4. 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:

FeatureLegacy StorageScoped Storage
File AccessFull external storageApp-specific + MediaStore
PrivacyLowHigh
CompatibilityWorks up to Android 9Required from Android 10+

Best Practices for Kotlin Scoped Storage

  1. Use MediaStore for images, videos, and audio files.
  2. Use getExternalFilesDir() for private app storage.
  3. Avoid deprecated APIs like Environment.getExternalStorageDirectory().
  4. 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.

rysasahrial

Leave a Reply

Your email address will not be published. Required fields are marked *