프로그래밍/Android

Android 13 - Granular media permissions

계발꿈나무 2022. 5. 23. 16:42
반응형

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://developer.android.com/about/versions/13/behavior-changes-13#:~:text=Granular%20media%20permissions,-Figure%201.&text=If%20the%20user%20previously%20granted,shown%20in%20the%20preceding%20table.

https://proandroiddev.com/notification-runtime-permission-android13-190c796254d5

반응형