How do I remove unused resources from third-party libraries I’ve included on Android?

AndroidPerformanceGradleApkAndroid Resources

Android Problem Overview


The third-party libraries that I link into my app often include resource files that aren’t being used by my application, and as such, end up bloating my APK.

For example, including the Google Play services library, but not using the login button functionality; all those image and layout resources end up in my final build.

Since these resources are included in a compiled library, how can I remove them from my build?

Android Solutions


Solution 1 - Android

> This answer is summarized from Removing Unused Resources which explains how to use minifyEnabled and shrinkResources, which are covered in more depth at the Official document page.

It’s a common problem for third-party libraries to include assets that your application codepath does not use, and it’s critically important to remove those assets in order to produce smaller APK files for your users. Thankfully, the latest version of Gradle and Android Studio provides a solution to help.

By setting minifyEnabled and shrinkResources to true in your Gradle configuration, the system will go forth removing unused resources from your application.

android {
    ...

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

It is important to note that removing unused resources requires the minifyEnabled flag to be set. This flag (as mentioned in Removing unused code) will trigger ProGuard to remove code paths that aren’t being used by your application. This is an important step in the removal of resources from included libraries. If the code paths aren’t removed, then the compiler will still believe the resources are referenced by an existing codepath and won’t remove them properly.

It's worth noting that this is a pretty extensive system. For instance, it will look through specific string constants in your code, as well as various res/raw resources looking for any URLs in the form of file:///…. to keep. It will even go so far as to analyze CSS, HTML, and JavaScript files as well.

Now, there may be instances here of false positives or false negatives. Assets might be getting cut, or kept, when you want the opposite behavior. (To be fair, resource shrinking tends to be overeager...) To adjust this, you can add the tools:keep and tools:discard attributes to define the desired behavior, by convention in a res/raw/keep.xml file.

<resources xmlns:tools="http://schemas.android.com/tools"
     tools:keep= "@layout/l_used*_c,  @layout/l_used_b*"
     tools:discard="@layout/unused2"
/>

Solution 2 - Android

If you can't use shrinkResources for some reasons, at the least we can use resConfig to remove languages we don't support.

defaultConfig {
    resConfig "en"     
}

Solution 3 - Android

This is for Kotlin DSL (build.gradle.kts).

I'm using Gradle 7.4.2 and Android Gradle Plugin (AGP) 7.0.4.
Note the proguard-android-optimize.txt which optimizes more:

android {
    defaultConfig {
        resourceConfigurations += setOf("en", "fa") // Only keep English and Farsi
        // ...
    }

    buildTypes {
        release {
            isShrinkResources = true
            isMinifyEnabled = true
            signingConfig = signingConfigs["MySigningConfig"]
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
}

See Android Developers: Shrink, obfuscate, and optimize your app for more information.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionColt McAnlisView Question on Stackoverflow
Solution 1 - AndroidColt McAnlisView Answer on Stackoverflow
Solution 2 - AndroidRiyaz Mohammed IbrahimView Answer on Stackoverflow
Solution 3 - AndroidMahozadView Answer on Stackoverflow