Mygod Mygod - 4 months ago 66
Android Question

Android Build Tools keep ProGuard from removing unused appcompat library classes

Here's a part of my

build.gradle
:

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

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:21.0.3'
}


There's nothing in
proguard-rules.pro
but I noticed a file named
aapt_rules.txt
was generated which has something like this:

# view res/layout/abc_action_menu_item_layout.xml #generated:17
-keep class android.support.v7.internal.view.menu.ActionMenuItemView { <init>(...); }

# view res/layout/abc_expanded_menu_layout.xml #generated:17
-keep class android.support.v7.internal.view.menu.ExpandedMenuView { <init>(...); }

# view res/layout/abc_list_menu_item_layout.xml #generated:17
# view res/layout/abc_popup_menu_item_layout.xml #generated:17
-keep class android.support.v7.internal.view.menu.ListMenuItemView { <init>(...); }

# view res/layout/abc_screen_toolbar.xml #generated:27
-keep class android.support.v7.internal.widget.ActionBarContainer { <init>(...); }

# view res/layout/abc_action_mode_bar.xml #generated:19
# view res/layout/abc_screen_toolbar.xml #generated:43
-keep class android.support.v7.internal.widget.ActionBarContextView { <init>(...); }

# view res/layout/abc_screen_toolbar.xml #generated:17
-keep class android.support.v7.internal.widget.ActionBarOverlayLayout { <init>(...); }

# view res/layout/abc_screen_content_include.xml #generated:19
-keep class android.support.v7.internal.widget.ContentFrameLayout { <init>(...); }

# view res/layout/abc_screen_simple_overlay_action_mode.xml #generated:23
-keep class android.support.v7.internal.widget.FitWindowsFrameLayout { <init>(...); }

# view res/layout/abc_screen_simple.xml #generated:17
-keep class android.support.v7.internal.widget.FitWindowsLinearLayout { <init>(...); }

# view v11/res/layout-v11/abc_screen_content_include.xml #generated:19
-keep class android.support.v7.internal.widget.NativeActionModeAwareLayout { <init>(...); }

# view res/layout/abc_action_mode_close_item_material.xml #generated:17
# view res/layout/abc_search_dropdown_item_icons_2line.xml #generated:27
# view res/layout/abc_search_dropdown_item_icons_2line.xml #generated:37
# view res/layout/abc_search_dropdown_item_icons_2line.xml #generated:48
# view res/layout/abc_search_view.xml #generated:116
# view res/layout/abc_search_view.xml #generated:128
# view res/layout/abc_search_view.xml #generated:38
# view res/layout/abc_search_view.xml #generated:60
# view res/layout/abc_search_view.xml #generated:97
-keep class android.support.v7.internal.widget.TintImageView { <init>(...); }

# view res/layout/abc_screen_simple.xml #generated:25
# view res/layout/abc_screen_simple_overlay_action_mode.xml #generated:32
-keep class android.support.v7.internal.widget.ViewStubCompat { <init>(...); }

# view res/layout/abc_action_menu_layout.xml #generated:17
-keep class android.support.v7.widget.ActionMenuView { <init>(...); }

# view res/layout/abc_activity_chooser_view.xml #generated:19
-keep class android.support.v7.widget.LinearLayoutCompat { <init>(...); }

# view res/layout/abc_search_view.xml #generated:78
-keep class android.support.v7.widget.SearchView$SearchAutoComplete { <init>(...); }

# view res/layout/abc_screen_toolbar.xml #generated:36
-keep class android.support.v7.widget.Toolbar { <init>(...); }


Which obviously keeps everything used by XMLs in the support library even if those XMLs are not used at all. And the codes that are kept again keeps all the resources from being skipped using
shrinkResources true
. And the apk size increased a lot even nothing in the support library is used. The same thing goes with other libraries.

So is there a way to customize
aapt_rules.txt
or do something like that to remove those unused code and resources? (or do I need to open an issue for this somewhere?)

Answer

You can see there are comments in aapt_rules.txt. Beside each kept class there are corresponding layout files that referenced this class. Like that:

# view res/layout/abc_list_menu_item_layout.xml #generated:17
# view res/layout/abc_popup_menu_item_layout.xml #generated:17
-keep class android.support.v7.internal.view.menu.ListMenuItemView { <init>(...); }

If you remove the layout file from build process this line will desappear and class will not be kept. The class will be shrinked if it's not actually used somewhere.

So how can we remove layout file from appcompat library? I can see few options, none of them is perfect but they work.

  1. You can just remove file from sdk\extras\android\m2repository\com\android\support\appcompat-v7\version\appcompat-v7-version.aar. Enough for testing, bad for production because the same file may be used in some other projects. I tried and it works.

  2. Put fake file with the same name into your project. Name conflict will happen. Build process will prefer your fake file because project files have higher priority. This way file from appcompat will be ignored. I tried and it works.

  3. Probably you can make some fance gradle script that removes unwanted files during the build process. I haven't tried that.

(shrinkResources option doesn't help because aapt_rules.txt is generated BEFORE shrinkResources is actually involved.)

I hope somebody will suggest a better way to do that

After doing that all unwanted lines were gone from aapt_rules.txt. But it saved me about 100 KB from the final apk size. So not big deal for me. But in your case results may be different.

Comments