Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to successfully obfuscate project with Dagger 2.0 using Proguard?

I was happy to see google's fork of Dagger has been made available. (At the time of this writing, I realize that it is not "released" yet.) we have an android app which uses dagger heavily, although we do not use many of the more advanced features.

We have a business requirement to obfuscate our code, so I have have attempted an upgrade to Dagger 2.0-SNAPSHOT in the hopes that the removal of runtime reflection from Dagger would make it possible to run obfuscation.. however I'm finding that reflection is still used in terms of string constants being used at runtime to load classes.

Below is the relevent bits of my proguard.conf.

-dontpreverify
-keepattributes *Annotation*,JavascriptInterface,SourceFile,LineNumberTable,Signature
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

-ignorewarnings

-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.app.Fragment
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference

-keep class android.support.v4.app.** { *; }
-keep interface android.support.v4.app.** { *; }

-keep public class * extends android.view.View {
    public <init>(android.content.Context);
    public <init>(android.content.Context, android.util.AttributeSet);
    public <init>(android.content.Context, android.util.AttributeSet, int);
    public void set*(...);
}

-keepclasseswithmembernames class * {
    native <methods>;
}

-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet);
}

-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet, int);
}


###### dagger 2.0 stuff
-keep class dagger.** { *; }
-keep interface dagger.** { *; }
-keepnames class com.ourcompany.**

-keep class **$$ModuleAdapter { *; }
-keepnames class **$$InjectAdapter { *; }

-keepclassmembers class * {
    @javax.inject.Inject <fields>;
    @javax.inject.Inject <init>(...);
}
-adaptclassstrings

As you can see I have turned off much of the obfuscation. This allows for some classes to be injected properly, however it still fails on injecting one paticular class.

Here is the exception:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.ourcompany.mobile.ourapp/com.ourcompany.mobile.ourapp.MainActivity}: java.lang.IllegalStateException: Unable to create binding for com.ourcompany.mobile.ourapp.LogMetricsHelper
E/AndroidRuntime( 7228):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2195)
E/AndroidRuntime( 7228):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
E/AndroidRuntime( 7228):    at android.app.ActivityThread.access$800(ActivityThread.java:135)
E/AndroidRuntime( 7228):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
E/AndroidRuntime( 7228):    at android.os.Handler.dispatchMessage(Handler.java:102)
E/AndroidRuntime( 7228):    at android.os.Looper.loop(Looper.java:136)
E/AndroidRuntime( 7228):    at android.app.ActivityThread.main(ActivityThread.java:5017)
E/AndroidRuntime( 7228):    at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 7228):    at java.lang.reflect.Method.invoke(Method.java:515)
E/AndroidRuntime( 7228):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
E/AndroidRuntime( 7228):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
E/AndroidRuntime( 7228):    at dalvik.system.NativeStart.main(Native Method)
E/AndroidRuntime( 7228): Caused by: java.lang.IllegalStateException: Unable to create binding for com.ourcompany.mobile.ourapp.LogMetricsHelper
E/AndroidRuntime( 7228):    at dagger.internal.Linker.linkRequested(Linker.java:147)
E/AndroidRuntime( 7228):    at dagger.ObjectGraph$DaggerObjectGraph.getInjectableTypeBinding(ObjectGraph.java:320)
E/AndroidRuntime( 7228):    at dagger.ObjectGraph$DaggerObjectGraph.inject(ObjectGraph.java:290)
E/AndroidRuntime( 7228):    at com.ourcompany.mobile.module.ScopedActionBarActivity.onCreate(ScopedActionBarActivity.java:20)
E/AndroidRuntime( 7228):    at com.ourcompany.mobile.ourapp.BaseActivity.onCreate(BaseActivity.java:68)
E/AndroidRuntime( 7228):    at com.ourcompany.mobile.ourapp.MainActivity.onCreate(MainActivity.java:146)
E/AndroidRuntime( 7228):    at android.app.Activity.performCreate(Activity.java:5231)
E/AndroidRuntime( 7228):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
E/AndroidRuntime( 7228):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2159)
E/AndroidRuntime( 7228):    ... 11 more

Has anyone tried out proguard with Google's dagger fork yet?

like image 642
derekv Avatar asked Sep 24 '14 19:09

derekv


People also ask

What is ProGuard obfuscation?

ProGuard is a command-line tool that reduces app size by shrinking bytecode and obfuscates the names of classes, fields and methods. It's an ideal fit for developers working with Java or Kotlin who are primarily interested in an Android optimizer.

What is ProGuard jar?

ProGuard is a free shrinker, optimizer, obfuscator, and preverifier for Java bytecode: It detects and removes unused classes, fields, methods, and attributes.


Video Answer


1 Answers

Latest Dagger 2.0 SNAPSHOT (as of writing this) plays nicely with ProGuard. I added no rules for Dagger 2 in my ProGuard config. Everything just works.

BTW I'm also using ButterKnife and greenDAO in my project. Both need 3-4 ProGuard rules.

like image 75
mindex Avatar answered Nov 16 '22 01:11

mindex