Android 打包编译开启了shrinkResources true,导致 Resources.getIdentifier() 使用的动态资源被移除的问题

问题

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" 
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容