Resource Shrinking去掉无用的资源
来源:互联网 发布:淘宝缺货赔付规则 编辑:程序博客网 时间:2024/05/19 06:39
http://blog.csdn.net/nwsuafer/article/details/41943997
Resource Shrinking
The Gradle build system for Android supports "resource shrinking": the automatic removal of resources that are unused, at build time, in the packaged app. In addition to removing resources in your project that are not actually needed at runtime, this also removes resources from libraries you are depending on if they are not actually needed by your application. For example, your application is using Google Play Services to for example access Google Drive functionality, and you are not currently using Google Sign In, then this would remove the various drawable assets for the Sign In buttons.
Note that resource shrinking only works in conjunction with code shrinking (such as ProGuard). That's how it can remove unused resources from libraries; normally, all resources in a library are used, and it is only when we remove unused code that it becomes apparent which resources are referenced from the remaining code.
To enable resource shrinking, update your build type as follows:
android {
...
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
Again, you have to enable
minifyEnabled
in order to turn on code shrinking, and then shrinkResources
to turn on resource shrinking. If you have not already been using minifyEnabled
, make sure you get that working before also adding shrinkResources
, since you may have to edit your proguard-rules.pro
file to make sure any methods you access with reflection etc are listed as keep rules in that file.When you enable
shrinkResources
, building your app should display output like the following during the build:...
:android:shrinkDebugResources
Removed unused resources: Binary resource data reduced from 2570KB to 1711KB: Removed 33%
Note: If necessary, you can disable resource shrinking by adding
android {
buildTypes {
debug {
shrinkResources false
}
}
}
:android:validateDebugSigning
...
If you want to see which resources are actually removed, you can supply the
--info
flag to the Gradle command, which will cause it to display a lot of extra information; if you look for the string "Skipped unused resource" you'll see output like the following:$ ./gradlew clean assembleDebug --info | grep "Skipped unused resource"
Skipped unused resource res/anim/abc_fade_in.xml: 396 bytes
Skipped unused resource res/anim/abc_fade_out.xml: 396 bytes
Skipped unused resource res/anim/abc_slide_in_bottom.xml: 400 bytes
Skipped unused resource res/anim/abc_slide_in_top.xml: 400 bytes
Skipped unused resource res/anim/abc_slide_out_bottom.xml: 400 bytes
Skipped unused resource res/anim/abc_slide_out_top.xml: 400 bytes
Skipped unused resource res/color/rating_bar_label.xml: 472 bytes
Skipped unused resource res/drawable-xhdpi-v4/big.png: 866901 bytes
Skipped unused resource res/drawable-xhdpi-v4/ic_action_add_schedule.png: 282 bytes
Skipped unused resource res/drawable-xhdpi-v4/ic_action_remove_schedule.png: 368 bytes
Skipped unused resource res/drawable-xhdpi-v4/ic_livestream_pause.png: 1694 bytes
Skipped unused resource res/drawable-xhdpi-v4/ic_livestream_play.png: 2141 bytes
Skipped unused resource res/drawable-xhdpi-v4/ic_media_route_on_holo_light.png: 1594 bytes
Skipped unused resource res/drawable-xxhdpi-v4/actionbar_icon.png: 2002 bytes
Skipped unused resource res/drawable-xxhdpi-v4/ic_action_overflow.png: 330 bytes
Skipped unused resource res/drawable-xxhdpi-v4/ic_action_play_dark.png: 331 bytes
Skipped unused resource res/drawable/photo_banner_scrim.xml: 620 bytes
Skipped unused resource res/drawable/session_detail_photo_gradient.xml: 620 bytes
Skipped unused resource res/drawable/transparent_background_pattern.xml: 436 bytes
Skipped unused resource res/layout/activity_letterboxed_when_large.xml: 360 bytes
Skipped unused resource res/menu/sessions_context.xml: 1088 bytes
Skipped unused resource res/raw/keep.xml: 262 bytes
Skipped unused resource res/transition-v21/shared_element.xml: 1008 bytes
Skipped unused resource res/transition-v21/window_enter_exit.xml: 108 bytes
Keeping Resources
You can tell the build system about resources you want to keep with the special tools:keep
attribute, similar to how ProGuard configuration files can list classes and methods to keep. It doesn't matter which XML resource file you place this in, but a good practice is to keep it in a file such as res/raw/keep.xml
(and don't worry; unless you reference this resource as R.raw.keep from your .java source files, this resource will be removed along with the other unused resources from the packaged app!).
The value of the keep attribute can be a comma separated list of resource references to keep, and they can also use the asterisk character as wildcards. Example:<?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*"/>
You can also specify tools:discard to deliberately remove resources that were kept:<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
tools:shrinkMode="safe"
tools:discard="@layout/unused2" />
tools:keep
attribute, similar to how ProGuard configuration files can list classes and methods to keep. It doesn't matter which XML resource file you place this in, but a good practice is to keep it in a file such as res/raw/keep.xml
(and don't worry; unless you reference this resource as R.raw.keep from your .java source files, this resource will be removed along with the other unused resources from the packaged app!).<?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*"/>
You can also specify tools:discard to deliberately remove resources that were kept:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
tools:shrinkMode="safe"
tools:discard="@layout/unused2" />
Strict Versus Safe
Normally, the build system can accurately determine whether a resource is used or not. However, if your application makes a call to
Resources#getIdentifier
(or if any of your libraries do that -- and note that the appcompat library does), then that means that the app can be looking up resources names on the fly, based on Strings that it computes dynamically. When the build system sees that call, it tries to be more defensive. That's because your code could contain something like this: String name = String.format("img_%1d", angle + 1);
res = getResources().getIdentifier(name, "drawable", getPackageName());
img_
as potentially used (and therefore not eligible for shrinking).It's possible that your code will contain many strings that are overly broad. You can optionally turn off this "better safe than sorry" handling, and ask for the resource shrinker to only consider resources referenced if it's certain. In that case it will be up to you to manually keep resources that you are referencing at runtime. This is similar to how code shrinking already works; you have to provide a proguard configuration file where any classes referenced by reflection are explicitly kept.
To turn off the safety checks, set the shrinkMode to "strict" as in the following keep.xml file:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
tools:shrinkMode="strict" />
Diagnostics
To track down problems with resource shrinking (such as "why did resource X get removed?" or "why didn't resource Y get removed?"), you can use the
--debug
flag to the gradle command. This will cause a lot of diagnostic output to be printed, so you'll probably want to send the output to a file:$ ./gradlew assembleDebug --info > /tmp/build-output.txt
For example, let's say I want to know why @drawable/ic_plus_anim_016 is still in my APK:
$ cat /tmp/build-output.txt | grep drawable/ic_plus_anim_016 | grep reachable
16:25:48.052 [QUIET] [system.out] @drawable/ic_plus_anim_016 : reachable=true
In the build output resource reference graph, I find that it's referenced from a different resource:
16:25:48.005 [QUIET] [system.out] @drawable/add_schedule_fab_icon_anim : reachable=true
16:25:48.009 [QUIET] [system.out] @drawable/ic_plus_anim_016
Therefore, I now need to know why
@drawable/add_schedule_fab_icon_anim
is reachable -- and if I search upwards I find that that resource is listed under "The root reachable resources are:
". This means that there was a code reference toadd_schedule_fab_icon_anim
(e.g. its R.drawable
id was found in the reachable code.).If we are not using strict checking, resource id's can be marked as reachable if there are string constants which look like they may be used to construct resource names for resources loaded dynamically. In that case, if you search the build output for the resource name you may find a message like this:
10:32:50.590 [QUIET] [system.out] Marking drawable:ic_plus_anim_016:2130837506 used because it format-string matches string pool constant ic_plus_anim_%1$d.
If you see one of these strings, and you are certain that the String is not being used to load the given resource dynamically, you can use the
tools:discard
attribute (described under "Keeping Resources" above) to inform the build system to remove it.(There are some additional details on how to diagnose resource shrinking in this bug report: https://code.google.com/p/android/issues/detail?id=80872.)
Resource URLs
In addition to looking for calls to Resources#getIdentifier, the build system will also look through all the String constants in your code, as well as various
res/raw
resources, looking for resource URLs of the form file:///android_res/drawable//ic_plus_anim_016.png
. If it finds these, or strings that look like they may be used to construct resources like these, it will mark these resources as used and will not shrink them. For raw resources in particular, it attempts to analyze .html, .css and .js files lexically such that it for example will ignore Strings that aren't used in URLs or in JavaScript literals that could be used to build up a resource URL.Res Configs
In addition to removing unused resources, you can also use the Android Gradle plugin's "resConfigs" feature to have it remove any resource configurations that you app does not need.
For example, let's say the messages in your application have not been translated and are all in English. If you are using a library such as Google Play Services, you are picking up translations for all of the messages in those libraries. When functionality in the library is accessed, those will be shown to the user. Whether you prefer that, or want to have the whole app use a single language, is up to you. But if you choose to have a single language, or more generally, just the languages your app is targeting, you can set that up in your build.gradle file, and then at build time all other languages are dropped (which will make your APK smaller, similar to the resource shrinking facility).
Here's what you add to your build.gradle file if you for example want to limit your languages to just English and French:
android {
defaultConfig {
...
resConfigs "en", "fr"
}
}
You could also add
resConfigs "nodpi", "hdpi"
to for example also limit the density folders that are packaged, and in gene 0 2
- Resource Shrinking去掉无用的资源
- 【Android Studio】Resource Shrinking去掉无用的资源
- android studio 去掉无用资源
- eclipse去掉无用的validation
- 【android】使用android-resource-remover删除项目中无用的资源,减少包的大小
- AndroidStudio清除无用的资源
- 去掉DataGrid的ViewState中的无用数据
- 去掉DataGrid的ViewState中的无用数据
- 去掉DataGrid的ViewState中的无用数据
- 去掉ViewState中DataGrid的无用数据
- 去掉Query无用的过滤InfoObject
- 去掉DataGrid的ViewState中的无用数据
- 去掉DataGrid的ViewState中的无用数据
- git 去掉已经暂存的无用文件
- eclipse优化之去掉无用的validation
- eclipse 去掉无用的 validation 优化eclipse
- android lint 去除无用的资源
- studio删除无用的文件资源
- 黑马程序员——Swift学习笔记:闭包
- linux安裝mongodb
- 常用的linux命令
- java web 编解码
- strcpy 不能用 unsigned char[]
- Resource Shrinking去掉无用的资源
- B2C电子商务系统研发——商品SKU分析和设计(一)
- c++中格式化输出。十六进制浮点数0x p输出问题
- UINavigationController方法pushViewController:参数不能传递UITabBarController原因猜想
- node 单元测试实践
- B2C电子商务系统研发——商品SKU分析和设计(二)
- 常用的免费的开源软件
- HDU 1023.Train Problem II【大卡特兰数】【9月25】
- vim插件之AutoComplPop和OmniCppComplete的安装和使用