Why does adding 'debuggable true' to my Android release build type eliminate a cryptic error?

Viewed 4137

I've been developing on an app for a while and testing against the debug build type with no build issues. Today, I tried building the release build type and I get the error

Error: Expected resource of type drawable [ResourceType]

This error occurs in a Butterknife-generated .java file. After quite a bit of trial and error (including doing a clean and invalidating caches) I discovered that the build succeeds if I add debuggable true to the release build type in my app build.gradle file, thus:

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

It also builds if I comment out the other properties thus:

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

But the build fails as before if I also comment out debuggable true. So it appears that no matter what I need to have debuggable true in my release build type even though I don't want it there.

Any ideas what might be causing this? More importantly, any idea how I can get the error to go away without debuggable true and without suppressing lint warnings?

(I've tried suppressing the lint error ResourceType on the particular declaration in the hand-coded .java file but to no avail. TBH, I don't want to go into production with a solution like that.)

1 Answers

Sounds to me like you are facing an obfuscation problem. Proguard is used to remove dead code and shrink your package size before installing. Typically minifyEnabled = true on release builds. making it debuggable likely prevents it from doing this.

There is a proguards rule file that tells it to make exceptions. Here is how it works.

Proguard combs your code and looks for unused code like "lint" and then removes it as no one ever calls the code.

However, tools like Bus or Butterknife use reflection or annotation to access code. This makes the IDE and LINT believe it is unused and it gets removed. therefore the code will not compile in release properly as it will be missing necessary components for the project to function.

Consider either setting minifyEnable = false or try adding this to your proguard rules file

-keep class butterknife.*
-keepclasseswithmembernames class * { @butterknife.* <methods>; }
-keepclasseswithmembernames class * { @butterknife.* <fields>; }

If that still doesn't work, you may have something else going on. The strange part is the missing "resource" piece, it makes me think that unused resources are being removed due to butterknife as well. So I would not leave debuggable in there, I would just set minifyEnabled = false if the above solution doesn't fix it.

If that doesn't work, then try running:

bash gradlew assembleRelease --debug and look for the actual complaints and problems from there.

Best of luck and hopefully that fixes ya.

Related