问题
release 版本的包上出现图片无法显示的问题,出现以下错误日志:
android.content.res.Resources$NotFoundException: Drawable ******:drawable/** with resource ID #0x7f08012e
之前在 debug 版一直没有出现,因为用的 SDK 需要把图片资源放到 drawable 下,分析了下 apk 包,发现相应的图片资源没有被打包进来,起初认为是混淆的原因,但是混淆只是针对代码,后发现了这个配置 shrinkResources true
Android 打包设置 shrinkResources true 引发的问题分析
当配置 shrinkResources 的值为 true 时,gradle 在打包编译的时候会将未引用的例如图片等资源文件移除。
shrinkResources 必须和 minifyEnabled 配合使用达到减少包体积的作用,只有删除了无用的代码之后,才能知道哪些资源是无用的,如果想查看那些资源未使用可以使用如下命令:
./gradlew clean assembleDebug --info | grep "Skipped unused resource"
一些 SDK 使用 getResources().getIdentifier() 动态获取图片,开启 shrinkResources true 后,无用资源被删除,导致 getResources().getIdentifier() 调用的地方出现问题。
int drawableId = getResources().getIdentifier("icon", "drawable", getPackageName()) ;
解决方案
保留使用到的图片,使用是并没有在程序中引用,在打包时也开启了 shrinkResources 的值为 true 移除无用资源,和混淆可以配置 keep 类似,资源同样也可以通过tools:keep来指定要保留的资源文件,通常通过 res/raw/keep.xml
指定要保持的资源,如
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
tools:keep="@mipmap/ic_like_icon,@mipmap/ic_share_icon,@layout/l_used_a">
</resources>
同样可以通过 tools:discard
来从保持的资源中指定要删除的资源,如
tools:discard="@layout/unused2"