Android APK slimming practice: How to reduce the size of the second slimming? (4M-2.9M)

Before losing weight

Because size restrictions are usually taken into consideration, a lot of work has been done. The current status is listed below:

7.3M (Debug version) and 6.5M (Release version). Turn on minifyEnabled. Turn on shrinkResources. Large irrelevant libraries have been removed. Images and code have gone through a rough round of cleaning.

Start the devil’s weight loss

1. tinypng lossy compression

Android packaging itself will perform lossless compression on png. If you don’t believe it, you can check that the size of the pictures in the apk is actually smaller than the pictures in your code project (for those png pictures that have not been losslessly compressed).

Therefore, pure lossless compression will not have any effect on reducing the size of the apk. This is an experience I particularly want to emphasize here. The tinypng that everyone prefers to use now is actually lossy compression:

https://tinypng.com/ [Original] TinyPNG uses smart lossy compression techniques to reduce the file size of your PNG files… [Translation] TinyPNG uses smart lossy compression techniques to reduce the file size of your PNG files… [Translation] TinyPNG uses smart lossy compression techniques to reduce the size of your PNG files…

Tinypng can indeed reduce the size of the apk with as little loss as possible. If there are many or large image resources, the effect is still very obvious. The specific reduction is because we do this process at intervals and cannot give accurate results. Let’s calculate it as 200k~500k.

2. Change png to jpg

Experience has found that some background, startup page, and promotional page PNG images are relatively large, and the graphics of these images are relatively complex. If you switch to lossy JPG, it may be less than half (of course it is lossy, but by setting the compression parameters, this loss can be compared too small to ignore).

Because they are all large images, this method can effectively reduce the size of the apk.

3. Replace jpg with webp

If the large png image is still very large when converted to jpg, or you want to compress it smaller without reducing the image quality, then you can consider webp.

Android 4.0+ only natively supports webp, but our app is compatible with 2.3+, so devices below 4.0 will not be able to see images. 1. Considering that the total proportion of all our devices below 4.0 is about 0.44%, which is very small. Devices below 2.4.0 will not crash. We choose not to do webp compatibility processing below 4.0, and it will not be displayed if it is not displayed. Otherwise, you need to introduce webp related so files to increase the apk size.

By replacing the following four large pictures with webp and configuring the quality parameter of webp to 50 (it is said that 75 is the best value in official evaluation), the clarity is barely acceptable. This value is determined according to product requirements.

img

Install the jpg to webp tool:

brew install webp

The conversion command is as follows

cwebp-q input.jpgoutput.webp//
 Example:cwebp -q 50 a.jpg a.webp

Finally, theapk was reduced by 188k.

4. Reduce the size of the image

If after the above steps, there is still a big picture, it means that the picture is indeed a bit too big, maybe it really is a bit too big!

So, the question to consider is, is it necessary to ensure such a size? Can it be reduced? If this aspect can be reduced, the effect of apk slimming will inevitably be taken to a higher level.

5. Overwrite some default large images in aar

Some aar libraries contain images that are not useful at all. The most typical one is that the support-v4 compatibility library contains some images that “may” be used, but will not actually be used in your app.

img

I didn’t replace all the pictures, I just replaced a few larger pictures (the selected pictures) with 1×1 pictures. If there are 9patch pictures, they should be replaced with 3×3 9patch pictures.

The support library may be pretty good, but if some libraries reference some large images without knowing it, you can search and check in the res directory of each aar library under /build/intermediates/exploded-aar/.

apk reduced by 18k.

If you have any questions, you can join the technical exchange group to discuss together~

6. Delete armable-v7 package so

Thanks to @杨伟__ and @kymjs Zhang Tao for their reminders. The armable-v7 and armable folders can only keep armable.

Of course, the armable-v7a library will greatly improve graphics rendering, because we are mainly business dynamic libraries, so deleting it will not cause any harm.

img

apk reduced by 191k.

7. WeChat resource compression and packaging

This solution has been mentioned online, but there has been no demand or motivation to practice it before. I would like to thank @ naked Kaizi brother for his recommendation and communication. His apk can be reduced to 1M, and the effect is quite amazing. I tested this step after many subsequent steps of compression. The compression results at each stage will be slightly different, so the data is for reference only.

img

With normal compression, the apk package is reduced by 464k. If 7zip is enabled, the apk package is reduced by 594k.

apk reduced by 594k.

PS: Regarding this compression, I integrated it into the gradle script and created a new Task. The approximate code is as follows:

task compressReleaseApp {<!-- -->
    // Generate the existing release version into the compressed directory
    def appid = "appid"
    def channel = "abcdefghijkl"
    def guardJarFile = file('../AndResGuard/andresguard-1.1.jar')
    def guardConfigFile = file('../AndResGuard/config.xml')
    def originApkFile = file("../app.${appid}/build/outputs/apk/release/${appid}-release-${rootProject.ext.versionName}-${rootProject.ext.versionCode}- ${channel}.apk")
    def outputDir = file("../app.${appid}/build/outputs/apk/compressed/")
    def keystoreFile = file(RELEASE_STORE_FILE)
    //Start executing the compression command
    def proc = "java -jar ${guardJarFile} ${originApkFile} -config ${guardConfigFile} -out ${outputDir} -signature ${keystoreFile} ${RELEASE_STORE_PASSWORD} ${RELEASE_KEY_PASSWORD} ${RELEASE_KEY_ALIAS}".execute ();
    proc.waitFor();
    println "return code: ${ proc.exitValue()}" + ", stderr: ${proc.err.text}" + " stdout: ${proc.in.text}"
}

config enables 7zip, part of the configuration is as follows:

<?xmlversion="1.0"encoding="UTF-8"?>


<resproguard>


    <!--defautpropertytoset -->


    <issueid="property">


        <seventzipvalue="true"/>


        <!-- ... -->


    </issue>


 


    <issueid="whitelist"isactive="true">


        <pathvalue="com.xxx.yyy.R.drawable.emoji_*"/>


        <pathvalue="com.xxx.yyy....
 />


    </issue>


 


    <issue id ="compress"
 isactive="true">


        <!-- ... -->


    </issue>


</resproguard>
8. proguard deeply obfuscated code

For the sake of simplicity, many packages were simply ignored before. Now strict mode is enabled to confuse everything that can be confused:

img

Comparison of the final effects using WeChat compression scheme:

img

apk reduced by 215k.

PS: After obfuscation, it must be strictly tested. Sometimes it is even difficult to find errors. For example, I turned on strict obfuscation and after using it for a while, I slowly discovered two bugs. After excluding the two package programs, it became normal.

9. Deep cleaning of code and resources

What’s interesting is that no matter when and where I clean up code and resources, I always make new discoveries:

  • Newly discovered or newly introduced useless images
  • How are these pictures the same?
  • This class seems useless
  • Pictures related to useless classes are also useless
  • Some pictures can be replaced with coloring schemes
  • Some pictures can be replaced by shape
  • It seems that ic_luancher.png in hdpi can also be deleted

apk reduced by 66k.

10. Proguard removes symbol table

In order to retain debugging information before, we retained the symbol table in Proguard:

-keepattributes SourceFile,LineNumberTable

I think we should try to keep this as an official channel. Now for promotion channels, we can only use special means to annotate this line.

apk reduced by 230k.

ps: In the future, Umeng will have to work harder to find bugs in promotion channels and upload mapping.txt manually.

11. provided keyword

You can set the provided keyword for libraries that are only needed at runtime and are not actually packaged:

provided'com.android.support:support-annotations:22.0.0'

I have not found such a scenario. If there is one, it is support-annotations. However, after subsequent testing, support-annotations will be minifyEnabled in the release version, so setting provided for support-annotations is meaningless. .

If you have any actual scenes, please leave a message to explain, we will be very grateful.

apk is not reduced.

12. Emoticon pack online

Although there are not many emoticons in the application, only about 50, if these emoticons can be put online, it will not only effectively reduce the apk size, but also facilitate later expansion of support:

img

Packaged into emoji_v1.zip, the size is 202k. Now put emoji_v1.zip online, download it as needed and use it. The final comparison results are as follows:

img

apk reduced by 193k.

13. Coloring scheme compatible with all versions

The main purpose of considering the coloring scheme is to make it easier to support multiple themes, reduce the UI workload, reduce a lot of selector files in the project, etc., and then, by the way, reduce the apk size. Through the coloring scheme, we removed more than 10 solid-color pressed state pictures and corresponding xml, etc.

apk reduced by 15k.

PS: You can refer to the specific implementation, and I have integrated it into my LessCode library: DrawableLess.java

14. Remove duplicate libraries

Found two places:

  • Now I find that Qiniu’s SDK references android-async-http-1.4.6.jar. Although it is not big, only 95.4k, I feel that I can write a lightweight jar. Controlling it within 10 to 20k is enough. Specifically Can be implemented on top of existing network libraries.
  • My project uses UIL, but the imported third-party library references picasso. Two duplicate image download libraries are completely useless.

This part has not been dealt with yet, new tasks are involved, and optimization is postponed, so stay tuned.

img

15. Remove useless libraries

This is a very basic point, but it is easily overlooked. When you review it carefully, there are some useless functions or libraries that are almost useless. Might as well just remove it.

For example, very early on, I deleted sharesdk in our app because it was meaningless from the perspective of our product positioning and promotion.

16. Remove Baidu statistics

This is decided on a case-by-case basis.

Because our APP contains two statistical systems, Umeng and Baidu, the early boss requested it. In fact, the data in this area is rarely seen later. The data collected by Baidu statistics is almost useless and can be removed temporarily.

The original jar according to Baidu statistics is more than 130k, and the reduction of apk after removal will be far less than that.

apk reduced by 20k.

17. Use smaller libraries

Using a smaller library should not be the deciding factor in your choice, but it can be used as a reference factor (freso is indeed too large, and this size can also be a deciding factor).

Do you know how big the library for image downloading, network requesting, json parsing, etc. is compared to its competing products?

Take tool libraries as an example. There are many tool libraries on the Internet, but their sizes are often difficult to control.

  • xutils-3.2.6.aar – 843.8k
  • lite-common-1.1.3.jar – 148.1k
  • lesscode-core-0.8.2.aar – 64k

The last library above, LessCode, is a collection of tool classes I collected myself. It is very small: LessCode, which is less than 50k in size after obfuscation.

It not only improves development efficiency and reduces redundant code, but also avoids referencing some other large libraries, effectively avoiding the increase in package size.

For example, we have encountered such a bug. Clicking a button quickly triggers jumps multiple times. Now RxJava combined with RxBind has such a scenario solution. If these libraries are introduced, the apk size will inevitably increase. In fact, it only takes a few lines of code. , I integrated such a solution into LessCode. Next time other projects encounter such a problem, I don’t have to hesitate to introduce such a large library.

It is recommended that you summarize these small tool libraries based on your own experience, not seeking perfection, but seeking refinement!

img

18. Plug-in

The embarrassing thing is that most of the functions we present are important and indivisible functions that are difficult to separate from the business.

This year I plan to implement a lightweight plug-in solution, whether using someone else’s or writing it myself, hoping to solve or optimize some problems with installation packages loading multiple modules, theme switching, or hot fixes.

Here is a backup plan.

19. Functional and business trade-offs

When we first started thinking about downsizing, the leadership allowed us to cut off some functions appropriately. Because we have already achieved our 4M goal, we haven’t yet reached the point of cutting off functions.

Here is a backup plan.

Supplement

After the article was published, I received some suggestions from friends and would like to add a few points.

1. Remove useless language resources

Thanks to @马志兴 for the suggestion. By configuring resConfigs, you can choose which languages to package only, and then remove the languages from all over the world in various aar packages, especially those in the support package.

img

The choice of language to retain depends on the users and market of the product. If you only select the default English and Chinese languages, the configuration is as follows

android{<!-- -->


    defaultConfig{<!-- -->


        resConfigs"zh"


    }


}

Take a look at the effect:

img

If the WeChat compression scheme is not used for comparison, the apk is reduced by 197k. If you use WeChat compression (7zip turned on) to compare the results, the apk is only reduced by 16k, because WeChat has powerfully compressed resources.arsc, which is amazing!

apk reduced by 16k.

2. Delete x86 package so

Thanks again to @杨伟__ for the suggestion. After the x86 package was deleted, the test response seemed that some machines were prone to crashing and failed to pass strict testing, so the main version was restored and this measure was only implemented in individual channels.

Normally there will be no problem. After testing the effect, the apk was reduced by 78k.

Here is a backup plan.

Summary

In the end, we successfully reduced the apk size to 2.9M. If we continue to do the missing steps above, we should be able to reduce it even further.

The response from customers was so small that the leaders couldn’t believe it~

It is not difficult to lose weight, but the devil is to lose weight!

If you think the article is well written, please give it a like? If you think the article is very good, please forward it so that more friends can see it; if you think it deserves improvement, please leave me a message. I will definitely check carefully and correct any deficiencies, thank you~

img

For more Android advanced guides, you can Scan the code to unlock “Android Ten Major Section Documents”

1. Android vehicle application development system study guide (with actual project practice)

2. Android Framework study guide to help you become a system-level development expert

3.2023 Latest Android Intermediate and Advanced Interview Questions Summary + Analysis, Say Goodbye to Zero Offers

4. Enterprise-level Android audio and video development learning route + project practice (with source code)

5. Android Jetpack builds high-quality UI interfaces from entry to proficiency

6. Flutter technology analysis and practical implementation, the first choice for cross-platform

7. Kotlin improves the architectural foundation in all aspects from entry to actual use

8. Advanced Android plug-in and componentization (including practical tutorials and source code)

9. Android performance optimization practice + 360° all-round performance tuning

10. From beginner to proficient in Android, the path to advancement for experts

It’s not easy to code, so pay attention. ?( ′?` )