The official version of Android 13 will be released soon
So compared to the first developer experience version, now Android 13 has entered the stage of platform stability, which means that the API has basically been fixed, and there will be no major changes.
So I reviewed the important new features and behavior changes of Android 13 again, and found that there is one major change that was barely mentioned in the first developer experience version, and that is the runtime permission change of Android 13.
Therefore, today I will write another list of runtime permission changes in Android 13 to give you a comprehensive understanding of all runtime permission changes in Android 13.
Granular media permissions
Google has further refined local data access permissions on Android 13.
It can only be said that Google has spared no effort to protect user privacy, and today’s move has actually been laid out for a long time in advance.
As early as the Android 10 system, Google disabled the direct access of local files through absolute paths, but to access through the MediaStore API, we call this function Scoped Storage.
In addition, the pictures, audio or video contributed by our application to the media library will automatically have its read and write permissions, and there is no need to apply for additional READ_EXTERNAL_STORAGE
and WRITE_EXTERNAL_STORAGE
permissions. If you want to read pictures, audio or video contributed by other applications to the media library, you must apply for the READ_EXTERNAL_STORAGE
permission. The WRITE_EXTERNAL_STORAGE
permission will be deprecated in a future Android version.
This part of the description looks basically correct before Android 13. Although the WRITE_EXTERNAL_STORAGE
permission has not been abandoned, it is almost impossible for us to use it in various scenarios.
However, in Android 13, in order to allow users to manage media permissions more finely, Google started with the READ_EXTERNAL_STORAGE
permission first.
Starting from Android 13, if your application targetSdk is specified to 33 or above, the READ_EXTERNAL_STORAGE
permission will be completely useless, and applying for it will have no effect.
Correspondingly, Google has added three runtime permissions: READ_MEDIA_IMAGES, READ_MEDIA_VIDEO, and READ_MEDIA_AUDIO
, which are used to manage the photos, videos and audio files of the phone respectively.
That is to say, in the past, you only needed to apply for a READ_EXTERNAL_STORAGE
permission. This is no longer possible. You have to apply for it on demand, so that users can learn more precisely which media permissions your app has applied for.
As for the code to apply for runtime permissions, it is the same template, and there is nothing special about it. Here, I will post a version for you to apply with the Activity Result API. Since I have not yet adapted PermissionX to Android 13, I have not been able to demonstrate it to you for the time being. I will write another article after the adaptation is completed.
class MainActivity : AppCompatActivity() {
private val requestPermissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestPermission()) { granted ->
if (granted) {
// User allow the permission.
} else {
// User deny the permission.
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val requestBtn = findViewById<Button>(R.id.request_btn)
requestBtn.setOnClickListener {
if (Build.VERSION.SDK_INT >= 33) {
requestPermissionLauncher.launch(Manifest.permission.READ_MEDIA_IMAGES)
}
}
}
}
Code language: HTML, XML (xml)
As you can see, the ActivityResult
API is used here to apply for the READ_MEDIA_IMAGES
permission. If you haven’t learned about the Activity Result API, you can refer to this article for a detailed explanation of the Activity Result API. It’s time to give up startActivityForResult
The operation effect is shown in the following figure:

The strange thing is that here I only apply for the permission to read photos in the code, but the screenshot shows that we are applying for the permission to read photos and videos. And I verified locally that these two permissions are indeed granted together. Audio permissions are not granted together with them and need to be applied for separately.
My guess is that both permissions belong to the same permission group, so as soon as one is granted, the other is granted automatically. But I didn’t find any instructions on this in the official documentation, so please don’t do any business logic based on this behavior when writing code, because the permission group Google may be adjusted at any time, we should still follow our own business needs , apply for permission as needed.
In addition, in order to consider backward compatibility, we should write this when declaring permissions in 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>
Code language: HTML, XML (xml)
As you can see, API 32 is Android 12 and below, and we still declare the READ_EXTERNAL_STORAGE
permission. Starting with Android 13, we will use READ_MEDIA_IMAGES, READ_MEDIA_VIDEO, READ_MEDIA_AUDIO
instead.
The same logic processing should be done when applying for permissions in the code, so it will not be posted here.
Notify runtime permissions
Notification runtime permissions can be said to be one of the blockbuster features of Android 13. After all these years, Google has finally incorporated notifications into runtime permission management.
The notification bar is really a thing that people love and hate. I believe this sentence does not need to be explained, and everyone who uses Android phones should understand it.
In the previous Android system, any application that wanted to send a notification did not need the user’s consent, and it could send it if it wanted. This makes our mobile phone notification bar often occupied by some junk notifications, and the really important notifications may be difficult to find.
In order to solve this problem, Google has made many changes and adjustments. For example, the notification channel added in Android 8.0 is to help users better filter useful notifications and junk notifications.
But the addition of the notification channel only makes it easier for users to filter out those useless notifications and junk notifications that are not of interest, and block them. In essence, each application can still send notifications at will without the user’s consent at all.
This time, Android 13 incorporates notifications into runtime permission management, which means that if you want to send notifications in the future, you must first obtain user consent and authorization.
Let’s talk about how to apply for the permission to send notifications on Android 13. In fact, it is no different from the general runtime permission. First declare the permission to send notifications in AndroidManifest.xml
:
<manifest ...>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<application ...>
...
</application>
</manifest>
Code language: HTML, XML (xml)
Then we use the Activity Result API again to request permissions:
class MainActivity : AppCompatActivity() {
private val requestPermissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestPermission()) { granted ->
if (granted) {
// User allow the permission.
} else {
// User deny the permission.
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val requestBtn = findViewById<Button>(R.id.request_btn)
requestBtn.setOnClickListener {
if (Build.VERSION.SDK_INT >= 33) {
requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
}
}
}
}
Code language: HTML, XML (xml)
The operation effect is shown in the following figure:
In terms of usage, there is no difference between applying for permission to send notifications and other runtime permissions, but there are still many details worthy of our attention.
One of the points that must be noted, the POST_NOTIFICATIONS
permission is only useful if the application’s targetSdk
is specified as 33
or higher.
When the targetSdk is 32 and below, the system will think that you have not done the adaptation work for Android 13, and applying for the POST_NOTIFICATIONS permission will have no effect.

Correspondingly, it will pop up a dialog like the one shown above when you first create a notification channel.
And if the user chooses Don’t allow at this time, there will be no chance to see this dialog again, that is, the user permanently refuses our permission to send notifications. until the following two situations occur:
- The user uninstalled and reinstalled our app.
- We upgraded targetSdk to 33 or higher.
In addition, when a user’s phone is upgraded from Android 12 to Android 13, the ability to send notifications for installed apps does not change.
That is, if a user blocks our app’s notifications on Android 12, our app won’t have permission to send notifications when the device is upgraded to Android 13.
But as long as the user doesn’t explicitly block our app’s notifications on Android 12, our app will automatically be granted permission to send notifications after the device is upgraded to Android 13.
Finally, if you want to determine whether a runtime permission is authorized, you can usually write it like this:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS)
== PackageManager.PERMISSION_GRANTED) {
// Permission granted
} else {
// Permission not granted
}
Code language: JavaScript (javascript)
But this way of writing has an obvious drawback in judging the permission to send notifications, because it can only be used on Android 13, and systems below Android 13 do not have the POST_NOTIFICATIONS permission
.
So if it is just to judge whether our application has the ability to send notifications for users to see now, we can use the following writing method, which will ensure that it can work normally on each system version:
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
if (notificationManager.areNotificationsEnabled()) {
// Permission granted
} else {
// Permission not granted
}
Code language: JavaScript (javascript)
Other new permissions
These are the new permissions on Android 13 that need our attention the most, but they’re not all.
There are also some relatively small new permissions that may be used very rarely by everyone. Here is a brief summary.
Last year, Google added several Bluetooth-related runtime permissions to Android 12. The reason is that when developers access some Bluetooth-related interfaces, they need to apply for geographic location permissions, which makes some privacy-sensitive users very disgusted.
This is a historical issue. In order to better protect user privacy, Google added BLUETOOTH_SCAN, BLUETOOTH_ADVERTISE, and BLUETOOTH_CONNECT
to Android 12, these three runtime permissions. In this way, when developers need to access Bluetooth-related interfaces, they only need to request these Bluetooth permissions.
In this year’s Android 13, Google extended the protection of user privacy to the WIFI field.
Similar to Bluetooth, when developers access some WIFI-related interfaces, such as hotspots, WIFI direct connection, WIFI RTT, etc., they also need to apply for geographic location permissions.
This is actually a historical problem, and users certainly cannot understand why they need to authorize geographic location permissions when using some WIFI functions.
To this end, a new NEARBY_WIFI_DEVICES
permission has been added to Android 13. When using the WIFI API related to the above scenarios, we only need to apply for the NEARBY_WIFI_DEVICES permission, thus better protecting the privacy of users.
Another change is motion sensor permissions.
Before, if we wanted to read the data of the mobile phone’s motion sensor, we needed to apply for the BODY_SENSORS
permission. In Android 13, Google added another limitation to the BODY_SENSORS
permission that can only be used in the foreground.

It can be seen that when applying for the BODY_SENSORS
permission on Android 13, the user can only authorize the use in the foreground.
So what if our app just wants to get motion sensor data in the background? Don’t worry, Android 13 has added a BODY_SENSORS_BACKGROUND
permission, just apply for this permission.
It should be noted that, before applying for BODY_SENSORS_BACKGROUND
permission, you must first obtain BODY_SENSORS
authorization, otherwise the application will be invalid. This setting is a bit like the setting that Android 10 added background access to geographic location permissions.
Well, the above is a list of Android 13 runtime permission changes, I hope it will be helpful to you.