Android 13 - Granular media permissions
Affected when?
- Application targets Android 13
Added new permissions
Android 12 | Android 13 |
![]() |
![]() |
New permissions
Applications must request one or more new permissions instead of the READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE permissions.
The set of permissions that you request depends on the type(s) of media that your app needs to access:
Type of media | Permission to request | Remarks |
Images and photos | https://developer.android.com/reference/android/Manifest.permission#READ_MEDIA_IMAGES | |
Videos | https://developer.android.com/reference/android/Manifest.permission#READ_MEDIA_VIDEO | |
Audio files | https://developer.android.com/reference/android/Manifest.permission#READ_MEDIA_AUDIO | |
Files and documents | https://developer.android.com/reference/android/Manifest.permission#READ_EXTERNAL_STORAGE | Recommended set android:maxSdkVersion="32" |
Note: You don't need to declare the WRITE_EXTERNAL_STORAGE permission at all anymore. (Scoped storage from Android 10)
Photos & videos
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
Music & other audio
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
Files and documents
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
In Android 13,
If the user previously granted your app the READ_EXTERNAL_STORAGE permission, the system automatically grants each of the new permissions to your app.
From settings,
TargetSdkVersion < 33 | TargetSdkVersion = 33 | |
Only have a READ_EXTERNAL_STORAGE permission | Adds new permissions, changed not to allowed |
|
![]() |
![]() |
![]() |
From runtime permission,
TargetSdkVersion < 33 | TargetSdkVersion = 33 | |
Only have a READ_EXTERNAL_STORAGE permission | Adds new permissions, changed not to allowed |
|
![]() |
![]() |
![]() |
Read images/videos/audio from File, MediaStore
Android OS Tiramisu | READ_EXTERNAL_STORAGE | READ_MEDIA_IMAGES READ_MEDIA_VIDEO |
||
requestLegacyExternalStorage X | requestLegacyExternalStorage = true | requestLegacyExternalStorage X | requestLegacyExternalStorage = true | |
TargetSdkVersion < Tiramisu | File O MediaStore O |
File O MediaStore O |
File X MediaStore X |
File X MediaStore X |
TargetSdkVersion = Tiramisu | File X MediaStore X |
File X MediaStore X |
File O MediaStore O |
File O MediaStore O |
Read files File, MediaStore?
- Android 10 can access a pdf file with File class (OK) (requestLegacyExternalStorage, READ_EXTERNAL_STORAGE Permission)
- Android 11 can't access a pdf file with File class (NOT OK) (requestLegacyExternalStorage, READ_EXTERNAL_STORAGE Permission)
- but a file picker is OK (without READ_EXTERNAL_STORAGE Permission)
How to fix
// app/build.gradle
android {
compileSdkPreview "Tiramisu"
defaultConfig {
applicationId "com.example.examplefgs"
minSdk 21
targetSdkPreview "Tiramisu"
}
// AndroidManifest.xml
<manifest ...>
<!-- Required only if your app targets Android 13. -->
<!-- Declare one or more the following permissions only if your app needs
to access data that's protected by them. -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<!-- Required to maintain app compatibility. -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
<application ...>
...
</application>
</manifest>
ExampleMainActivity.kt
class ExampleMainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_storage_permission)
val permissions = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
READ_IMAGE_PERMISSIONS
} else {
DEPRECATED_READ_PERMISSIONS
}
if (isNeedRequestImagePermissions()) {
requestPermissions(permissions)
return
}
}
private fun isNeedRequestImagePermissions(): Boolean =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
checkSelfPermission(
Manifest.permission.READ_MEDIA_IMAGES
) != PackageManager.PERMISSION_GRANTED
} else {
checkSelfPermission(
Manifest.permission.READ_EXTERNAL_STORAGE
) != PackageManager.PERMISSION_GRANTED
}
private fun isNeedRequestVideoPermissions(): Boolean =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
checkSelfPermission(
Manifest.permission.READ_MEDIA_VIDEO
) != PackageManager.PERMISSION_GRANTED
} else {
checkSelfPermission(
Manifest.permission.READ_EXTERNAL_STORAGE
) != PackageManager.PERMISSION_GRANTED
}
private fun isNeedRequestAudioPermissions(): Boolean =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
checkSelfPermission(
Manifest.permission.READ_MEDIA_AUDIO
) != PackageManager.PERMISSION_GRANTED
} else {
checkSelfPermission(
Manifest.permission.READ_EXTERNAL_STORAGE
) != PackageManager.PERMISSION_GRANTED
}
companion object {
private val DEPRECATED_READ_PERMISSIONS = arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE)
private val READ_IMAGE_PERMISSIONS = arrayOf(Manifest.permission.READ_MEDIA_IMAGES)
private val READ_VIDEO_PERMISSIONS = arrayOf(Manifest.permission.READ_MEDIA_VIDEO)
private val READ_AUDIO_PERMISSIONS = arrayOf(Manifest.permission.READ_MEDIA_AUDIO)
}
}
https://developer.android.com/about/versions/11/privacy/permissions
https://proandroiddev.com/notification-runtime-permission-android13-190c796254d5