Don’t be surprised. Android 12 has only been officially launched for a few months, and Android 13 is already here.
Yes, the Android 13 Developer Preview has now launched two version iterations, including many new features.
So why Android 13 is coming so soon

The picture above is Google’s annual schedule for releasing new Android systems. It can be seen that at the beginning of each year, Google will release the Developer Preview version of the new version of the Android system. In the middle and early days of each year, the Beta Release version will be released. In the middle and late stages, the platform will enter the stable period, and the Release Candidate version will be released at this time. At the end of the year, the Stable version of the new version of the Android system will be officially launched.
So, the Android 12 Stable version was just launched at the end of last year, and the Developer Preview version of Android 13 is coming soon.
If you want to try Android 13 now, there are two main ways, one is to use a Pixel 4 or later version of the Pixel system phone, the other way is to use the emulator that comes with Android Studio.
If you use a mobile phone, you need to flash the device. Using the emulator is very simple, just download the latest version of the system image. I will not demonstrate the specific operation steps here. For details, please refer to the official documentation:
https://developer.android.google.cn/about/versions/13/get
After completing the above steps, you can get the latest Android 13 system:

We can also go to the settings to check the version number of the current system. If you see 13 or Tiramisu (the internal code of Android 13) displayed, then you have succeeded.

What new features and changes Android 13 has brought
Next, let’s study what new features and changes Android 13 has brought. The following diagram shows the new features and changes of Developer Preview 1 I intercepted from the official website:

As can be seen from the above figure, the new functions and changes of Android 13 can be mainly divided into 4 parts, core functions, images, privacy and security, and user experience.
The core function part is mainly to add some API support for Java 11. Since Android programs are basically developed using Kotlin, this function has little effect on us.
The image part is not my technical expertise, I don’t have the confidence to explain this part clearly, so I skip it here.
Then the next privacy and security, and user experience are our focus. I will explain each new function and change listed in the figure.
privacy and security
Added WIFI runtime permission
Last year, Google added several Bluetooth-related runtime permissions to Android 12. The reason is because when developers access some Bluetooth-related interfaces, they need to apply for geographic location permissions.
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.
Since NEARBY_WIFI_DEVICES
is just a common runtime permission, and it is no different from other runtime permissions, I will not demonstrate its usage through code here.
If you want to see more detailed information about this permission, you can refer to the official website:
Intent filter blocks mismatched Intent
On Android 13, this is an important security change.
Let’s first look at the official definition of this security change. When your app interacts with other apps through an Intent, if the targetSdkVersion of the app is specified as Android 13 or higher, the Intent must match an element defined in the Intent filter to be successfully delivered.
The official definition seems a bit confusing, so let me explain it clearly with a simple example.
For example, we define the following content in the AndroidManifest.xml file of App A:
<activity
android:name="com.example.android13test.SharedActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Code language: HTML, XML (xml)
As you can see, the exported property of SharedActivity is set to true here, indicating that it can be called by other external apps. Then we declared in the tag that its action is send and the category is default.
Then, in App B, the following code can naturally be used to start the SharedActivity in App A:
val intent = Intent(Intent.ACTION_SEND) startActivity(intent)
Here we specify ACTION_SEND
in the Intent, which matches the action defined in SharedActivity
. The startActivity()
method will automatically add a default category to the Intent, so it matches the category defined in SharedActivity. If both action and category are matched at the same time, it can be started successfully.
But in addition to using the above code, we can also successfully start SharedActivity by writing:
val intent = Intent()
intent.component = ComponentName(
"com.example.android13test",
"com.example.android13test.SharedActivity")
startActivity(intent)
Code language: JavaScript (javascript)
Here, the package name of App A and the full class name of SharedActivity are clearly specified through ComponentName
. Even if action and category are not specified, it can still work normally, right?
That’s right, but only on Android 12 and below.
This new security change on Android 13 is to limit this security vulnerability that does not match any elements defined in the Intent filter, but can still interact across programs. Because your Activity may be called by other external programs in a way that you did not design.
However, there are a few exceptions to this security change limit:
The target Activity does not define any Intent filter. In this case, the target Activity can still be started by specifying the package name and class name.
Interactions between components within your own app are not subject to this restriction.
Intent issued by the system is not subject to this restriction.
Intents issued with root user privileges are not subject to this restriction.
Seeing this, I hope everyone can review the use of cross-program Intent in their apps. If any illegal use is found, fix it as soon as possible to avoid large-scale crashes on Android 13.
image picker
All I can say about the image picker is that it’s a lifesaver.
Android has been suffering from the picture selector for a long time. The album selector that comes with the system is really bad. I have never seen a few apps that use it. Basically, each app implements the picture selector by itself.
Implementing your own image picker introduced several problems. First, it is more complicated to implement, requiring a lot of code implemation, and the cost is very high. Second, it is necessary to apply for the Storage permission to access the user’s local storage space, which is not friendly to user privacy.
Therefore, in Android 13, Google finally put the picture selector on the agenda, creating a powerful and highly available system with its own picture selector, so that each app no longer has to build its own wheels. At the same time, since this is an image selector provided by the system, the App does not need to request Storage permission anymore, which is more friendly to user privacy.
According to the official description, this image selector will be very powerful, not only efficient in performance, but also deeply customizable, and can even search and sort images, etc. However, I haven’t been able to appreciate such a powerful function for the time being, and I don’t know if it is not perfect yet. But one thing I’m sure of, it’s really simple to use.
How simple is it? I’m afraid you don’t believe it, just two lines of code will do it:
val intent = Intent(MediaStore.ACTION_PICK_IMAGES) startActivityForResult(intent, 1)
Yes, this will open the image picker that comes with the system. All the following functions have nothing to do with us. The user will browse and select pictures in the picture selector interface provided by the system, and finally return the Uri of the selected picture to us through the onActivityResult() callback:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 1 && resultCode == Activity.RESULT_OK) {
val uri = data?.data
Glide.with(this).load(uri).into(findViewById(R.id.image_view))
}
Code language: JavaScript (javascript)
Here I pass the obtained image Uri to Glide, so that the image can be displayed. Results as shown below:

The whole process of choosing an image is a great experience.
But be careful that the picture selector is a half-screen state at first, and we need to manually drag it to make it full-screen.
This is deliberately designed by Google. If we can only select one image at a time, the default is half-screen state.
And if we allow the selection of multiple pictures at one time , then it will become a full-screen state by default.
It is very simple to specify that multiple images are allowed to be selected at one time, as shown below:
val maxNum = 5 val intent = Intent(MediaStore.ACTION_PICK_IMAGES) intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, maxNum) startActivityForResult(intent, 1)
As you can see, by passing in an EXTRA_PICK_IMAGES_MAX
parameter, you can specify how many images are allowed to be selected at one time. Results as shown below:

Next, there is another question. Now that we have selected multiple pictures at one time, how can we get all the Uri of these pictures selected by the user?
In this case, the API for obtaining Uri is different from before, but it is also very simple. It is written as follows:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 1 && resultCode == Activity.RESULT_OK) {
data?.let {
it.clipData?.let { clipData ->
for (i in 0 until clipData.itemCount) {
val uri = clipData.getItemAt(i).uri
// Handle uri with your logic
}
}
}
}
}
Code language: JavaScript (javascript)
I personally think that the image picker that comes with the system should be one of my favorite features in Android 13. But it also has an obvious disadvantage, that is, it can only be applied to the Android 13 system. For Android 12 and below systems, we still need to write our own image selector. This problem cannot be solved in the short term.
Here we have introduced the functions and changes of the privacy and security part of Android 13, and then enter the content of the user experience part.
User experience
Theme app icon
The theme application icon is a feature that has been rotten by many domestic mobile phone manufacturers, and now Google has finally standardized it.
Specifically, the icon styles of each application on the desktop are very different and different, and some users may prefer to use icons with a unified global style.
The theme application icon is to solve this problem, it can make all application icons on the desktop use the same theme style, the effect is as shown below:

It looks like the system has done everything for us, so what else do we need to do?
In fact, things are not that simple. If you drag the app icon you developed yourself to the desktop, you will find that something goes wrong:

It can be seen that the icons of our self-developed apps have not changed into a unified theme style like other apps. It also means that this function needs to be adapted.
Fortunately, the adaptation scheme is not complicated. First, we need to prepare an icon that meets the specifications. What are the specific specifications?
Must be a VectorDrawable image.
The icon should be in a 90 * 90 dp container, the logo part should only be 36 * 36 dp in size, and the maximum size should not exceed 60 * 60 dp, otherwise there is a risk of being cut off.
Icons should be flat, and if your icon must be 3d, use transparency to indicate a stereoscopic effect.
The official design diagram given by Google is as follows:

With the icons ready, the next thing is simple.
Remember the function of separating the foreground and background layers of application icons introduced by Google in the Android 8.0 system (for details, please refer to this article Android application icon micro-skills, adaptation of application icons in the 8.0 system )? Now we just need to add a new label on top of it.
Modify the res/mipmap-anydpi-v26/ic_launcher.xml file as follows:
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>
Code language: HTML, XML (xml)
As you can see, we have specified another icon through the label, and the icon specified here is the icon we designed in the previous step that meets the specifications.
Of course, instead of designing a separate icon, I directly reused the foreground icon that was automatically generated when the project was created. Now re-run the program, the effect is as shown below:

The adaptation of the theme application icon is completed.
Quick Settings API
To explain what the Quick Settings API is, first we have to know what Quick Settings are,
When you slide down the notification bar of your phone, the shortcut switches above are Quick Settings. Like we usually turn on Wifi and turn on the flashlight, we will use the Quick Settings function.
But did you know that in addition to using these Quick Settings that come with the system, we can also add our own custom Quick Settings.
To create a custom Quick Settings is very simple, just create a custom Serivce and let it inherit from TileService, as follows:
public class MyQSTileService extends TileService {
}
Code language: PHP (php)
Then register this MyQSTileService in AndroidManifest.xml according to the following rules:
<service
android:name="com.example.android13test.MyQSTileService"
android:label="My Test Tile"
android:icon="@drawable/ic_launcher_foreground"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"
android:exported="true">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE" />
</intent-filter>
</service>
Code language: HTML, XML (xml)
Now re-run the program, our custom Quick Settings has been registered to the system, but you will find that you cannot find it,this is because the custom Quick Settings are not excited by default, and we need to manually activate it before we can use it, we need to click the edit button, then find our custom Quick Settings in the candidate area, and then drag it to the active area by dragging it so that it can be used.

Do you feel not very convenient to operate? For many novice users, maybe they will never find this hidden Quick Settings.
The Quick Settings API is designed to solve this problem.
With the Quick Settings API, we can tell the user if they want to add our custom Quick Settings in the form of a popup. As long as the user clicks to agree, the addition can be completed with one click, instead of the cumbersome operation as before.
So how to achieve it? I will directly demonstrate the code, as follows:
val manager = getSystemService(Context.STATUS_BAR_SERVICE) as StatusBarManager
val componentName = ComponentName(
"com.example.android13test",
"com.example.android13test.MyQSTileService")
val icon = Icon.createWithResource(this, R.drawable.ic_launcher_foreground)
manager.requestAddTileService(componentName, "My Title Test", icon, {}, {})
Code language: JavaScript (javascript)
As you can see, a new requestAddTileService()
function has been added to the StatusBarManager class, which is used to add custom Quick Settings.
This function receives a lot of parameters, but we can only pass the most critical parameters, such as the class name of the component, icon, Title, etc. The last two parameters are not mandatory and can be used to monitor whether the addition is successful. I just passed empty parameters directly.
Then run this code, the effect is as shown below:

We checked in advance that there is no Quick Settings that we customized in the activated Quick Settings.
Next, click the button to execute the above code snippet. At this time, you will see that the system pops up a Dialog to ask the user if they want to add custom Quick Settings. Note that this Dialog is provided by the system, so we cannot modify its UI. .
When the user clicks Agree, the addition is successful. At this time, go to the activated Quick Settings to check, and you can find our custom Quick Settings.
Apply individual language settings
For a long time, Android phones can only set a system-wide language. After setting this language, all apps installed on the phone will display the text in this language as long as it supports this language, and if it does not support it, the text in the default language will be displayed.
This global rule that only one language can be set is not very convenient in some cases.
Android 13 finally brings good news in this, it allows us to set the language for each App individually, so that we can ignore the system-wide language setting.
So how to do it specifically? I’ll show you below:

We enter the system settings, select System -> Language & Input, you will find an option for App Languages. After clicking to enter, all the apps installed on the phone will be listed, and then you can set the language for each app individually.
This function does not require any adaptation by the App, as long as it is Android 13 and above, it will be available automatically.
But if your app wants to do something extra, that’s fine.
Google now allows us to directly switch the language of the App by calling the API inside the App, so that the user does not need to manually go to the system settings to operate.
This API is newly added to the Android 13 system, but considering the issue of backward compatibility, Google provides a backward compatible API in the AndroidX library, so that we can also switch the language of the App in systems below Android 13. So I just use the API provided by AndroidX directly:
val appLocale: LocaleListCompat = LocaleListCompat.forLanguageTags("xx-YY")
AppCompatDelegate.setApplicationLocales(appLocale)
Code language: JavaScript (javascript)
The xx-YY in the LocaleListCompat.forLanguageTags() function represents the language and region, such as en-US, zh-CN.
After calling the above code, your app will go through a restart and then use the new language set.
fast hyphenation
I personally feel that the function of hyphenation is rather useless, because its word segmentation always fails to achieve the effect I expect, so I rarely use it. But the new features of Android 13 have a section about word hyphenation connectors, so let’s talk about it.
The so-called hyphenation connector refers to that some words in some English sentences are relatively long and cannot be displayed on the same line, but when they are displayed on the next line, the content of the previous line is very empty and loose, so this You can choose to use a hyphenated connector.
Before using the hyphenated hyphen:

After using the hyphenated hyphen:

To enable the hyphenation connector feature is actually very simple, just specify the following properties for your TextView:
<TextView
android:hyphenationFrequency="[full|normal]"
/>
Code language: HTML, XML (xml)
The specified parameters will determine how often the TextView should calculate where the hyphenation should be used. If it is normal, the frequency will be lower, and if it is full, the frequency will be higher.
However, this is not actually a new feature. This feature has been available as early as Android 6.0, but since Android 10, this feature has been turned off by default.
The reason why Google turned it off is mainly performance, because it takes a lot of calculation to determine where to use the hyphenation connector, which slows down the rendering speed of the TextView.
The quick word hyphenation connector introduced in Android 13 is to solve performance problems.
According to Google’s official documentation, the performance of the quick hyphenation connector has been improved by 200% compared to the previous one, and it has almost no effect on the rendering speed of TextView, so we can use it with confidence.
The way to use it is to add a Fast after the previous attribute, such as fullFast or normalFast:
<TextView
android:hyphenationFrequency="[fullFast|normalFast]"
/>
Code language: HTML, XML (xml)
But as I said before, the hyphenation connector on Android, its segmentation effect is not good enough in my opinion. So even if the performance is improved by 200%, it is not very helpful for me.
One Reply to “A glance at Android 13 Developer Preview”