Performance optimization series

APP startup optimization

UI rendering optimization

Memory optimization

Image compression

Long figure optimization

Power optimization

Dex encryption

Dynamic replacement Application

Exploring the principle of hot fix for APP stability

APP continuous running process alive implementation

ProGuard compresses code and resources

APK limit compression

Introduction to the

As the project continues to iterate, the amount of code and resource files grows. If one day your boss or leader asks you to optimize the size of APK, you don’t know how to optimize it. It’s a little unreasonable. In this article, let’s analyze and optimize the size of APK together.

Analyze the APK resource usage

Note:

I found a popular open source project on GitHub. If you need it, you can download it and try it yourself.

AS Build/Analyze APK used directly by the analysis tool

As shown in the figure above, assets > classes.dex > res > lib.

So let’s see how we can reduce the size of APK,

Optimize APK volume in eight strides

1. Convert the image to webP format

Webp concept

WebP is an image file format that provides both lossy and lossless compression, derived from the video encoding format VP8. Originally released in 2010, WebP aims to reduce file size but achieve the same image quality as the JEPG format, with the hope of reducing the time it takes to send images over the web. On November 8, 2011, Google began making WebP support for lossless compression and transparent colors.

According to Google’s earlier tests, WebP’s lossless compression reduced the file size by 45% compared to PNGS found on the web. Even when PNGCRUSH and PNGOUT were used to treat these PNGS, WebP reduced the file size by 28%. For now, Webp can reduce image size by an average of 70%. WebP is the future of the image format.

PNG / JPG to Webp

Right-click on an image or folder and select Convert to Webp to compress a PNG/JPG image into a Webp image.

In the end, we only reduced the amount by less than 200 KB or so. It’s possible that the project’s image resources were not that big, just too many small images.

Application scenarios and advantages

  • The client software is embedded with Chromum-based WebView. The web pages applied in this type of browser can completely use WebP format to improve the speed of loading and rendering, regardless of compatibility.
  • For programs developed with Node-WebKit, WebP can reduce the size of the package.
  • Mobile applications or web games, the interface needs a lot of pictures, can be embedded in WebP decoding package, can save user traffic, improve access speed advantages:
  • For PNG images, WebP is 45% smaller than PNG.

2. Eliminate multilingualism

In the app/build. Gradle added

android{
    ...
    defaultConfig{
        ...
        // Keep Only English
        resConfigs "en"}}Copy the code

And here we see that we’ve lost about 200 kilobytes

3. Remove unnecessary SO libraries

By decompile the Android wechat version, we know that wechat only adapted the Armeabi-V7A architecture, so let’s delete the support of other libraries.

android{
    ...
    defaultConfig{
        ...
            ndk {
            // Set the supported SO library architecture
            abiFilters "armeabi-v7a"}}}Copy the code

Optimized another 600 KB or so. Go ahead.

4. Remove unnecessary resources Link check (delete with caution)

concept

Lint is a code scan analysis tool provided by Android Studio that can help us find structure/quality problems and provide solutions without requiring us to write out test cases by hand. With multiple iterations of code, it’s easy to leave behind useless code and resource files that can be cleaned up using Lint.

How do I use Link check

Open AS and go to Analyze > Run Inspection By Name > unused resources

To optimize the

It turns out that our link optimizes about 700 KB. Continue.

Pay attention to

Since link checks for references to determine whether a resource is being used, be careful when deleting it in this way.

If r.xx.xxx is not used directly, then the resource represented by this id will be considered unused.
int indetifier =getResources().getIdentifier("img_bubble_receive"."drawable", getPackageName()); getResources().getDrawable(indetifier);

Copy the code

5. Turn on confusion

If you don’t know what confusion is, can you suggest a look at my last article performance Optimization (xi) ProGuard on code and resource compression

Optimized for about 1.7m continued.

6. Remove shinkResource

  • Enable shinkResource = true

        buildTypes {
            release {
                minifyEnabled true
                shrinkResources = true
    
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
            debug {
                shrinkResources = true
                minifyEnabled true
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    Copy the code

It is possible that the link deleted unnecessary resources, so it is not being optimized

7. Enable delete useless resources (strict mode and normal mode) – I can not test this here, you can test the effect

Normal mode is also called custom mode

If you have specific resources that you want to keep or discard, create an XML file in your project that contains the

tag and specify each resource to keep in the Tools :keep attribute and each resource to discard in the Tools: Discard attribute. Both properties accept a comma-separated list of resource names. You can use asterisk characters as wildcards.

Such as:

<? xml version="1.0" encoding="utf-8"? > <resources xmlns:tools="http://schemas.android.com/tools"
    tools:keep="@layout/l_used*_c,@layout/l_used_a,@layout/l_used_b*"
    tools:discard="@layout/unused2" />
Copy the code

Save the file in the project resource, for example, res/raw/keep.xml. The build does not package this file into APK.

Specifying which resources to discard may seem silly because you could have removed them, but it can be useful when using build variants. For example, if you know that a given resource will ostensibly be used in the code (and therefore not removed by the compressor) but will not actually be used for a given build variant, you can put all the resources in the common project directory and then create a different keep.xml file for each build variant. The build tool may also not be able to correctly identify the resource as needed because the compiler adds an inline resource ID, and the resource analyzer may not know the difference between the actual referenced resource and the integer value in the code that happens to have the same value.

Strict mode

Under normal circumstances, the resource compressor can accurately determine whether the system is using resources. However, if your code calls Resources.getidentifier () (or any of your libraries makes the call – the AppCompat library does), this means that your code will query for the resource name based on a dynamically generated string. When you perform this call, by default the resource compressor takes defensive action, marking any resource with a matching name format as potentially used and unable to be removed.

For example, the following code marks all resources prefixed with IMG_ as used.

String name = String.format("img_%1d", angle + 1);
res = getResources().getIdentifier(name, "drawable", getPackageName());
Copy the code

The resource compressor will also browse through the code and all string constants in the various res/raw/ resources, looking for resource urls in formats like file:///android_res/drawable//ic_plus_anim_016.png. If it finds strings similar to them, or other strings that look like they could be used to build similar urls, it does not remove them.

These are examples of secure compression modes that are enabled by default. However, you can disable this “be prepared” approach and specify that the resource compressor keeps only the resources it determines to use. To do this, set shrinkMode to strict in the keep.xml file as follows:

<? xml version="1.0" encoding="utf-8"? > <resources xmlns:tools="http://schemas.android.com/tools"
    tools:shrinkMode="strict" />
Copy the code

If you do have strict compression mode enabled, and your code also references resources that contain dynamically generated strings (as shown above), you must manually preserve those resources using the Tools :keep property.

8. AndResGuard wechat resource compression solution

What is a AndResGuard

AndResGuard is a tool to reduce the size of the APK. It works like Java Proguard, but only for resources. It will shorten the originally lengthy resource path, such as res/drawable/wechat to R /d/a.

Why use AndResGuard

In previous development, we often only confused the code, the resource files were exposed to others, and all the file names in the RES folder were too readable.

The effect after use

AndResGuard configuration

  • In the project root directory build.gradle, add dependencies for the plugin:

     dependencies {
            classpath 'com. Tencent. Mm: AndResGuard - gradle - plugin: 1.2.16'
        }
    Copy the code
  • In the app directory, create the and_res_Guard. gradle file

apply plugin: 'AndResGuard'

andResGuard {
    mappingFile = null
    use7zip = true
    useSign = true
    keepRoot = false
    compressFilePattern = [
            "*.png"."*.jpg"."*.jpeg"."*.gif"."resources.arsc"
    ]
    whiteList = [
            // your icon
            "R.drawable.icon".// for fabric
            "R.string.com.crashlytics.*".// for umeng update
            "R.string.tb_*"."R.layout.tb_*"."R.drawable.tb_*"."R.drawable.u1*"."R.drawable.u2*"."R.color.tb_*".// umeng share for sina
            "R.drawable.sina*".// for google-services.json
            "R.string.google_app_id"."R.string.gcm_defaultSenderId"."R.string.default_web_client_id"."R.string.ga_trackingId"."R.string.firebase_database_url"."R.string.google_api_key"."R.string.google_crash_reporting_api_key"./ / au
            "R.string.umeng*"."R.string.UM*"."R.layout.umeng*"."R.drawable.umeng*"."R.id.umeng*"."R.anim.umeng*"."R.color.umeng*"."R.style.*UM*"."R.style.umeng*"./ / cloud
            "R.drawable.u*"."R.drawable.rc_*"."R.string.rc_*"."R.layout.rc_*"."R.color.rc_*"."R.id.rc_*"."R.style.rc_*"."R.dimen.rc_*"."R.array.rc_*"
    ]

    sevenzip {
        artifact = 'com. Tencent. Mm: SevenZip: 1.2.10'}}Copy the code
  • Add it to the build.gradle file under the app module

    apply from: 'and_res_guard.gradle'
    Copy the code
  • After packing the renderings

Resources are compressed by about 1M

conclusion

  1. The bigger the project, the more resources, the more obvious the effect.
  2. If you use Link to delete resources, be careful and back them up in advance.
  3. Because the project itself is only more than 10 M, we finally optimized 4.5 M. It’s not easy.