epoxy icon indicating copy to clipboard operation
epoxy copied to clipboard

ViewBinding and proguard rules for obfuscation

Open Davidvster opened this issue 4 years ago • 7 comments

If you are using the abstract class ViewBindingEpoxyModelWtihHolder and you have obfuscation with R8 enabled, then the code does not work because it is trying to get the reflected bind method from the ViewBinding class. Since bind is not part of the ViewBinding interface and gets added only in implementations the reflection is the only way to go.

To solve this the following rule should be added to proguard:

-keepclassmembers class <package name of your app>.databinding.**  {
    public <methods>;
}

Davidvster avatar Jan 25 '21 11:01 Davidvster

ViewBindingEpoxyModelWtihHolder failing once upgrading to compile sdk 31 and arctic fox gradle 7+. Funny thing is, it's crashing in the wrong xml! Not the one which is being used in that screen.

ubarua123 avatar Dec 12 '21 15:12 ubarua123

@ubarua123 what is the crash that you are getting, any chance of pasting the crash log?

Davidvster avatar Dec 12 '21 18:12 Davidvster

java.lang.NullPointerException: Missing required view with ID: com.muuzzer_wq.android.apps.readers_writers.community:id/header_title
at com.wonderquill.databinding.HoirzontalRowHeaderBinding.bind(HoirzontalRowHeaderBinding.java:5)

The controller where it crashed, wasn't even inflating this model. I have a build running in production with the same code.

It's only after I upgraded to:

JDK: 11 Gradle: 7.0.4 Arctic Fox

that all my problems started. Worst part is, it's working fine in debug. Obviously it has something to do with proguard. These are my proguard rules if that helps:

-keepclassmembers class * extends androidx.viewbinding.ViewBinding {
    public static *** bind(android.view.View);
}
-keepclassmembers class com.wonderquill.databinding.**  {
    public <methods>;
}

-keep class * implements androidx.viewbinding.ViewBinding {
    public static *** bind(android.view.View);
    public static *** inflate(android.view.LayoutInflater);
}

This is the model class:

@EpoxyModelClass(layout = R.layout.hoirzontal_row_header)
abstract class HorizontalHeaderModel : ViewBindingEpoxyModelWithHolder<HoirzontalRowHeaderBinding>() {

     override fun HoirzontalRowHeaderBinding.bind() {

     }
}

ubarua123 avatar Dec 13 '21 06:12 ubarua123

same scenario + 1

eric6300 avatar Dec 19 '21 10:12 eric6300

Both problems can be solved with this proguard rules

-keep class * extends $package.ViewBinding  { *;}
-keepclassmembers class * extends $package.ViewBinding  { *;}

-keep class * extends $package.path.to.ViewBindingEpoxyModelWithHolder  { *;}
-keepclassmembers class * extends $package.path.to.ViewBindingEpoxyModelWithHolder { *;}

and don't forget to change the class paths to point to your package for the ViewBinding classes and to ViewBindingEpoxyModelWithHolder class. Apparently R8 somehow messes up the classes and when the bind method of the ViewBinding class is trying to be resolved, this line

val genericSuperclass = klass.genericSuperclass

will incorrectly resolve the superclass. I've created a vanilla project and tried it with only my classes and the problem is there as well so it has nothing to do with Epoxy per se.

So the solution, even though I don't know the original cause, is to keep those EpoxyModels extending from ViewBindingEpoxyModelWithHolder and don't allow R8 to mess with them

davidbilik avatar Jan 12 '22 13:01 davidbilik

Have anyone experienced a new issue with R8 full mode with ViewBindingEpoxyModelWithHolder -

Fatal Exception: java.lang.NullPointerException: null cannot be cast to non-null type java.lang.Class<*>
       at x.ViewBindingEpoxyModelWithHolderKt.getSuperclassParameterizedType(ViewBindingEpoxyModelWithHolder.kt:42)

Dwite avatar Aug 15 '23 16:08 Dwite

Have anyone experienced a new issue with R8 full mode with ViewBindingEpoxyModelWithHolder -

Fatal Exception: java.lang.NullPointerException: null cannot be cast to non-null type java.lang.Class<*>
       at x.ViewBindingEpoxyModelWithHolderKt.getSuperclassParameterizedType(ViewBindingEpoxyModelWithHolder.kt:42)

Same here, a simple but rude fix was adding -keep class com.airbnb.epoxy.kotlinsample.helpers.** { *; } into proguard-rules.pro

shawnlinboy avatar Sep 14 '23 15:09 shawnlinboy