Android 13 Developer Preview at a Glance

This article is simultaneously published on my WeChat official account. You can follow by scanning the QR code at the bottom of the article or searching for Guo Lin on WeChat. Articles are updated every working day.

Don't be surprised. Android 12 has only been officially launched for a few months, and Android 13 is already here.

Yes, Android 13 Developer Preview has launched two version iterations, including many new features and behavior changes.

Originally, according to the habit of previous years, I would not study the new functions of the new system every year at such an early stage. However, since the company recently arranged for me to do an internal technology sharing involving this topic, I had a relatively comprehensive experience with Android 13 in the first place this year.

Since I was taking my personal breaks while preparing this sharing, I don't think it will be protected by the company's intellectual property rights. So today I will write an external article to share my learning and understanding of Android 13 Developer Preview.

Let's start by explaining why Android 13 is here so quickly.
insert image description here
The picture above is the timetable for Google to release the new Android system every year. It can be seen that at the beginning of each year, Google will release the Developer Preview version of the new Android system. In the middle and early days of each year, a Beta Release version will be released. In the middle and late ten days, the platform will enter a stable period, and the Release Candidate version will be released at this time. By the end of the year, the Stable version of the new Android system will be officially launched.

Therefore, 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 higher version of the Pixel system phone, and the other is to use the emulator that comes with Android Studio.

If you use a mobile phone, you need to flash it. Using the emulator is very simple, just download the latest version of the system image. I will not demonstrate the specific operation steps here, please refer to the official documentation for details:

https://developer.android.google.cn/about/versions/13/get

After completing the above steps, you can get the latest Android 13 system, as follows:

insert image description here

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 name of Android 13), it means you have succeeded.

insert image description here

Next, let's study what new features and changes Android 13 brings. The following picture is a new feature and change of Developer Preview 1 that I intercepted from the official website:

insert image description here

In fact, when I was preparing this article, Google just launched the version of Developer Preview 2, so if you go to the official website to check the new features and changes of Android 13, you will find that there are many more than what I have listed here.

But I don't expect to cover all the new features in one article, so let's just focus on the Developer Preview 1 version here.

As can be seen from the figure above, the new features and changes of Android 13 can be mainly divided into four parts, core features, graphics, 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 now, this function has little impact on us.

The image part is not my technical expertise, and I am not confident that I can explain this part clearly, so I will skip it here.

Then privacy and security, as well as user experience are our focus. I will explain every new function and change listed in the figure.


Added WIFI runtime permissions

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.

This is a problem left over from history. In order to better protect user privacy, Google added BLUETOOTH_SCAN, BLUETOOTH_ADVERTISE, BLUETOOTH_CONNECT, these three runtime permissions to Android 12. In this way, when developers need to access Bluetooth-related interfaces, they only need to request these Bluetooth permissions. For details, please refer to this article . PermissionX 1.6 is released and supports Android 12 .

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 problem left over from history. Users must not understand why they need to authorize geographic location permissions when using some WIFI functions.

For this reason, a new NEARBY_WIFI_DEVICES permission has been added in Android 13. When using the WIFI API related to the above scenarios, we only need to apply for the NEARBY_WIFI_DEVICES permission, which better protects the user's privacy.

Since NEARBY_WIFI_DEVICES is just a common runtime permission, and its usage is no different from other runtime permissions, I will not demonstrate its usage through code here.

If you want to view more detailed information about this permission, you can refer to the official website:

https://developer.android.google.cn/about/versions/13/features/nearby-wifi-devices-permission


Intent filter blocks unmatched Intents

On Android 13, this is a very important security change, and if you don't fully understand it, there may be a series of crashes by then.

Let's first look at the official definition of this security change. When your app interacts with other apps through Intent, if the targetSdkVersion of the app is specified as Android 13 or higher, then the Intent must match an element defined in the Intent filter to be successfully delivered.

The official definition seems a bit of a mouthful, let me explain it clearly through 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>

It can be seen that the exported attribute 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 category is default.

Then, in App B, the following code can naturally be used to start SharedActivity in App A:

val intent = Intent(Intent.ACTION_SEND)
startActivity(intent)

Here we specify ACTION_SEND in 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. Both action and category are matched at the same time, then naturally it can be started successfully.

But in addition to using the above code, we can also successfully start SharedActivity by writing the following:

val intent = Intent()
intent.component = ComponentName(
    "com.example.android13test", 
    "com.example.android13test.SharedActivity")
startActivity(intent)

Here, the package name of App A and the complete 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 kind of security vulnerability that does not match any element 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 is not designed by you.

However, there are a few exceptions to this security change restriction:

  1. 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.
  2. Interactions between components within your own application are not subject to this restriction.
  3. Intents issued by the system will not be subject to this restriction.
  4. Intents issued with root user permissions will not be subject to this restriction.

Seeing this, I hope that everyone can review the use of cross-program Intents in their apps, and if found to be illegal, fix them 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 new feature.

Android has been struggling with the picture selector for a long time. The album selector that comes with the system is really bad. I haven’t seen a few apps that use it. Basically, each App implements the picture selector by itself.

Implementing an image picker yourself presents several problems. First, it is more complicated to implement, a lot of code needs to be written, and the cost is very high. Second, you need to apply for Storage permission to access the user's local storage space, which is not friendly enough for user privacy.

Therefore, in Android 13, Google finally put the picture selector on the agenda to create a powerful and highly available system with its own picture selector, so that each App no ​​longer needs 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 permissions 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, sort, and so on images. However, I haven't experienced such a powerful function for the time being, and I don't know if it has not been perfected yet. But one thing I'm sure of, it's really easy to use.

How simple is it? I’m afraid you won’t believe me, just two lines of code will do it:

val intent = Intent(MediaStore.ACTION_PICK_IMAGES)
startActivityForResult(intent, 1)

Yes, in this way, the image selector that comes with the system can be opened. 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))
    }
}

Here I pass the obtained picture Uri to Glide, so that the picture can be displayed. Results as shown below:

insert image description here

The experience of the whole process of selecting pictures is excellent. You know, we only paid a very small price (basically equal to zero), and we didn't even apply for the Storage permission.

But careful friends may have noticed that this picture selector is in a half-screen state at the beginning, and we need to manually drag it to make it full-screen.

This is deliberately designed by Google. If we can only choose one picture at a time, the default is half-screen.

And if we allow multiple pictures to be selected at one time (for example, WeChat can select up to 9 pictures at a time), then it will become full-screen by default.

Next, let's verify it through the code. It is very simple to specify that multiple pictures 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)

It can be seen that by passing in an EXTRA_PICK_IMAGES_MAX parameter, you can specify how many pictures are allowed to be selected at one time. Results as shown below:

insert image description here

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, 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
                }
            }
        }
    }
}

I personally think that the system's own picture selector 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, Android 12 and below systems, we still need to write our own picture selector, this problem cannot be solved in the short term.

At this point, we have introduced the functions and changes of Android 13 privacy and security, and then enter the content of user experience.


Theme app icon

The theme application icon is a function that many domestic mobile phone manufacturers have done badly, and now Google has finally included it in the standardization.

Specifically, the icon style of each application program on the desktop is different and different, and some users may prefer to use icons with a uniform global style.

The theme application icon is to solve this problem, it can make all the application icons on the desktop use the same theme style, the effect is shown in the following figure:

insert image description here

It seems that 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 to the desktop, you will find something wrong:

insert image description here

It can be seen that the icons of the apps developed by ourselves have not become a unified theme style like other apps. At the same time, 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?

  1. Must be a VectorDrawable image.
  2. The icon should be in a 90 * 90 dp container, and the logo part should only have a size of 36 * 36 dp, and the maximum size should not exceed 60 * 60 dp, otherwise there is a risk of being cut off.
  3. Icons should be flat, and if your icon must be 3D, you can use transparency to indicate a three-dimensional effect.

The official design diagram given by Google is as follows:

insert image description here

With the icon ready, the rest is easy.

Do you still 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-tricks, the 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>

It can be seen that we have specified another icon through the label, and the specified icon here is the one we designed in the previous step that meets the specifications.

Of course, I did not design an icon separately, but directly reused the foreground icon that was automatically generated when creating the project. Now run the program again, the effect is as shown in the figure below:

insert image description here

The adaptation of the theme application icon is now complete.


Quick Settings API

To explain what is Quick Settings API, first we have to know what is Quick Settings.

You may not know what Quick Settings is, but I promise, you must have used it.

When you slide down the notification bar of your phone, the shortcut switches on the top are Quick Settings. Like we usually turn on Wifi and turn on the flashlight, we will use the Quick Settings function.

insert image description here

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.

It is very simple to create a custom Quick Settings, just create a custom Serivce and let it inherit from TileService, as follows:

public class MyQSTileService extends TileService {
    
    

}

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>

Now re-run the program, our custom Quick Settings has been registered in the system, but you will find that you cannot find it:

insert image description here

This is because the custom Quick Settings are not activated by default, and we need to activate them manually before they can be used:

insert image description here

As you can see, we need to click the edit button, then find our custom Quick Settings in the candidate area, and drag it to the active area by dragging and dropping, so that we can use it.

Have you ever felt very inconvenient to operate? For many novice users, perhaps 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 inform the user whether to add our custom Quick Settings in the form of a pop-up window. As long as the user clicks to agree, the addition can be completed with one click, without the need for cumbersome operations like before.

So how to achieve it? I will demonstrate the code directly, 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, {
    
    }, {
    
    })

It can be seen that a 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 component's class name, icon, Title, etc. The last two parameters are not mandatory and can be used to monitor whether the addition is successful, so I directly passed empty parameters.

Then run this code, the effect is as shown in the following figure:

insert image description here

We checked in advance, there is no our customized Quick Settings among the activated Quick Settings.

Next, click the button to execute the above code snippet. At this time, you will see a Dialog popped up by the system to ask the user whether 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 will find our customized Quick Settings.


Apply individual language settings

For a long time, Android phones can only set a system-global language. After setting this language, all Apps installed on the mobile phone will display text in this language as long as they support this language. If they do not support it, they will display text in the default language.

Only one language rule can be set globally, which is very inconvenient in some cases. For example, the language setting of my mobile phone is Chinese, but I need it to display English for some specific apps. In this case, I can only switch the system language to use that App, and I have to switch back after using it. And switching the system language every time is very resource-intensive, and my phone will be stuck for a while because of this.

Android 13 finally brings good news in this regard, it allows us to set the language for each App individually, so that we can ignore the global language setting of the system. This feature can be said to have saved users like me.

So how to do it? Let me show you the picture below:

insert image description here

We enter the system settings, select System -> Language & Input, and you will find that there is an additional App Languages ​​option. After clicking to enter, all the applications 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 some extra things, it's actually possible.

Google now allows us to switch the language of the App directly 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 a new addition 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 the system below Android 13. So I directly use the API provided by AndroidX:

val appLocale: LocaleListCompat = LocaleListCompat.forLanguageTags("xx-YY")
AppCompatDelegate.setApplicationLocales(appLocale)

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 undergo a restart and then use the new language set.


fast word breaker

I personally feel that the function of word hyphenation is rather tasteless, because its word segmentation always fails to achieve the effect I expected, so I rarely use it. But in the new features of Android 13, there is a part about hyphenated connectors, so let’s talk about it.

The so-called hyphenation symbol refers to the fact that certain words in some English sentences are too long to be displayed on the same line, but when displayed on the next line, the content of the previous line will appear empty and loose, so this When you can choose to use hyphenated connectors.

Before using hyphenated connectors:

insert image description here

After using a hyphen joiner:

insert image description here

It is actually very simple to enable the hyphenation connector function, just specify the following properties for your TextView:

<TextView
    android:hyphenationFrequency="[full|normal]"
/>

The specified parameters will determine how often TextView calculates where hyphenated connectors 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 actually not a new feature. It 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 closed it is mainly performance, because it takes a lot of calculations to determine where to use hyphenated connectors, which will slow down the rendering speed of TextView.

The fast hyphenation character introduced in Android 13 is to solve performance problems.

According to Google's official documentation, the performance of fast hyphenation has improved by 200% compared to before, 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 Fast after the previous attribute, such as fullFast or normalFast:

<TextView
    android:hyphenationFrequency="[fullFast|normalFast]"
/>

But as I said before, the segmented effect of hyphenation on Android is not good enough. So even if the performance is improved by 200%, it will not help me a lot.


epilogue

That's all about Android 13 Developer Preview 1.

Of course, Developer Preview 2 is now out, and it includes more new features and changes. But obviously, this article can't cover that much content, so the rest is waiting for you to explore by yourself.

If you want to learn Kotlin and the latest Android knowledge, you can refer to my new book "The First Line of Code 3rd Edition" , click here to view details .


Pay attention to my technical public account, and high-quality technical articles will be pushed every day.

Scan the QR code below on WeChat to follow:

Guess you like

Origin blog.csdn.net/sinyu890807/article/details/124061726