
Butter Knife is an annotation processing library that helps streamline boilerplate Java code in Android views. Its annotations are processed at compile time to generate the relevant UI code so that views function properly.
When obfuscating applications that use Butter Knife, there are specific configuration patterns you should follow. The code that connects generated classes to their views uses runtime reflection under the hood. Because of this, the original name of the View is required.
When configuring DashO, we need to:
1. Exclude from renaming any activity, view, or fragment containing the Butterknife.bind() directive.
2. Exclude from renaming any generated class named *_ViewBinding.
The DashO wizard helps us with proper configuration by identifying the MainActivity and any fragment as a non-renameable entry point. This means that you do not need to explicitly exclude the View or Fragment from Renaming. You only need to exclude the generated MainActivity_ViewBinding or Fragment_ViewBinding class. However, please note that it is also possible to have a class containing the Butterknife.bind() directive, which has not been identified as an entry point. If this is the case, we must exclude this and its ViewBinding class.
Let’s look at an example.
I have a MainActivity with a TextView decorated with the ButterKnife @BindView annotation.

I have a fragment with a button and a ButterKnife @OnClick that shows a toast.

After going through the DashO Wizard, the MainActivity and BlankFragment have been identified as non-renewable entry points:


I then create a Rename pattern Rule to ensure that any _ViewBinding doesn’t get renamed:

Based on this configuration, after obfuscation, my app loads and runs properly:

If I didn’t explicitly specify the *_ViewBinding Rename exclusion, I would see an exception in LogCat: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.the.basicexample/com.example.the.basicexample.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Please note: this example uses a newer version of Butter Knife. In versions before 8, instead of _ViewBinding, we would add **$$ViewBinder.
In conclusion, Butter Knife applications can be obfuscated with just a few basic configurations to ensure the generated code is handled correctly.
You can download the complete example here.
If you have any feedback on this topic or other topics you would like us to discuss in the Support Corner, please contact us by submitting a request here – Preemptive Support Center.