In order to reduce the size of the application as much as possible, we should remove unused code and resources in the release version. In addition, there are two optimization directions that can be used to reduce the space occupied by the application. One is to use the obfuscation function, which shortens the names of the application classes and members; the other is to use the optimization function , This feature will adopt a more aggressive strategy to further reduce the size of the application. This article will introduce how to use APK resource optimization to reduce application space and save user resources.

Ask a question

First use the product U-APM launched by Youmeng+ to actually test the usage of the application on different devices:

It can be seen from the figure that there is still room for optimization in the startup time of the application. In the next step, we will read the memory allocation of the application and determine from which direction we can optimize the resources to speed up the startup. time.

In order to analyze the above indicators in detail, we use the Memory tab on the Android window, which will show us the amount of data allocated on the heap over time:

The figure shows that a GC event has occurred, unused objects have been deleted and space on the heap has been released.

To investigate what is currently allocated in the heap, we can use the heap dump button on the left. This will take a snapshot of what is currently allocated in the heap and display it in a special report screen in Android Studio:

On the left, we see a histogram of the instances in the heap, grouped by class name. For each, there are the number of objects allocated, the size of these instances (shallow size), and the size of these objects kept in memory. The latter tells us how much memory can be released if these instances are released. This view gives us an important understanding of the memory usage of the application and helps us identify large data structures and object relationships. This information can help us build more efficient data structures, untie object connections to reduce reserved resources, and ultimately reduce resource usage as much as possible.

Subsequently, we used a single layout file to build the smallest APK to count the number of times the layout file name appears in the Android APK.

Only one AndroidManifest.xml file is required to build Android applications using Gradle. We can add a virtual layout.

Running gradle assembleRelease will produce a release APK with only 2,118 bytes. We can use dump its content xxd and find the home_view byte sequence.

According to this output, there are 3 uncompressed paths and 1 uncompressed name only in the APK.

A zip file is a list of file items, followed by a list of all available items. Each entry contains the file path, and so does the directory. This shows the first occurrence (item title) and the last occurrence (listing record) in the output.

The middle two appearing in the output come from inside the resources.arsc file, which is a database for sorting resources. Its content is visible because the file is not compressed in the APK. Run aapt dump --values resources

build/outputs/apk/release/app-release-unsigned.apk displays the home_view record and its mapping to the path:

The APK contains the fifth occurrence of the name in the classes.dex file. It is not shown in the xxd output because the file is compressed. Run baksmali dump <(unzip -p build/outputs/apk/release/app-release-unsigned.apk classes.dex) to display the string table of the dex file, which contains the following items

home_view:

This is used to map the R.layout layout name to a field in the class with only integer values. By the way, the integer is

The index of resources.arsc database, used to find related file names to read its XML content.

To summarize the answer to our question, for each resource file, the full path appears 3 times and the name appears twice.

optimized resources

Android Gradle plug-in 4.2 introduces an android.enable ResourceOptimizations=true flag, which will perform resource optimization. This will aapt optimize the commands to call the merged resources and resources.arsc files before they are packaged into the APK. The optimization only applies to the released version, regardless of whether minifyEnabled is set to true or not, it will run. After adding the logo, we can use diffuse reflection in gradle.properties to compare the two APKs to see the effect. The output is very long, so we will break it down by part.

The first is the difference in the contents of the APK. The "compressed" column is the cost within the APK, and the "uncompressed" column is the cost at the time of extraction.

The res category represents our single resource file, and its size has dropped by 28 bytes. This arsc category is used for resource.arsc itself, obviously, this produces a certain optimization.

These two parts represent the code and content of the resource database. No change, we can infer that the optimization has no effect

R.layout.home_view field and home_view resource entry.

Finally, the optimization effect is shown. The file name of our layout resource is clearly truncated and moved out of the layout/folder.

In the Gradle project, the XML folder and file name are meaningful. The folder is the resource type, and the name corresponds to the fields and resource entries created in the .arsc file. However, if these files are in the APK, the file path becomes meaningless. Resource optimization is optimized by making the name as short as possible.

The output of the aapt dump resource database also reflects the file changes:

All three occurrences of the path in the APK are now shorter, saving 36 bytes. Although 36 bytes is a very small number, the entire binary file is only 2,118 bytes. The 36 bytes saves 1.7% of resources.

Nick Butcher's Plaid application has 734 resource files. In addition to the quantity, the names of the resource files are more descriptive (which means they are more peculiar). The names contained in home_viewPlaid are searchback_stem_search_to_back.xml, attrs_elastic_drag_dismiss_frame_layout, and designer_news_story_description.xml.

The build without resource optimization is compared with the build that enables it:

Resource optimization saves 0.76% of APK size.

Uwe Trottmann's SeriesGuide application has 1044 resource files. Unlike Plaid, it has no native

Library, this should make the optimization effect better.

I updated the project to AGP 4.2 again and compared the two versions:

Here, resource optimization can reduce the size of the APK by 2.0%!

Chris Banes' Tivi app has an important sub-set written with Jetpack Compose, which means fewer overall resources. The current build still contains 776 resource files.

By using Compose, Tivi is already using the latest AGP 4.2. Through two quick builds, we can see the impact of resource optimization:

We once again achieved a 2.0% reduction in APK size

APK signature

APK signature has multiple versions. If your version minSdkVersion is lower than 24, you need to include version V1 when signing. V1 signature uses Java’s .jar signature specification, which treats each file as a text clause in the file with a separate signature META-

INF/MANIFEST.MF。

After creating and configuring the keystore for the original single-layout application, dump the manifest file unzip -c

build/outputs/apk/release/app-release.apk META-INF/MANIFEST.MF shows the following signature:

![](/img/bVcVZO2)

The complete path of each file appears, so that the total number of occurrences of each resource path reaches four times. Since a shorter name will again cause this file to contain fewer bytes, resource optimization has a greater impact in the signature.

__

According to data, this method can save 1-3% of APK size. According to actual tests, this range seems to be correct

of. The final cost savings will depend on the size and quantity of the resource files in the APK.


性能优化实践者
11 声望220 粉丝