Dagger + Proguard obfuscation, Errors creating object graph

android, dagger, proguard

Solution

Dagger 1.x has issues with obfuscation. It can do code-shrinking with appropriate -keep statements, but obfuscation becomes problematic because of the use of String keys. The Strings are generated prior to proguarding, but consumed after proguarding, and do not line up with the newly-renamed types.

Dagger 1.x (around 1.0.0) before we disabled reflective module adapters will work, as pure-reflection results in both provision and injection of a type to be considered "just in time" (i.e. after proguarding) so obfuscated types match up. If code-obfuscation is a higher priority than performance, do consider using this slightly older version.

Dagger 2.x (in progress) is free of string keys, and results in direct class references, and should play very nicely with Proguard. Stay tuned to the dagger lists and project. We expect early versions of 2.x to drop within weeks of this posting.

Also, and more specifically, make sure you `-keepattributes Signature`. The specific error you are seeing is because JDK5+ generics are being stripped by proguard. One never injects `Lazy`, one injects `Lazy<Foo>`. That will fix this specific error, though you will then have the problem mentioned above.

Problem

Running an obfuscated version of my application throws the following stacktrace ``` java.lang.RuntimeException: Unable to create service com.mycompany.myapp.async.alarms.AlarmIntentService: java.lang.IllegalStateException: Errors creating object graph: dagger.Lazy could not be bound with key dagger.Lazy required by dagger.Lazy com.mycompany.scheduler.c.mNotificationDisplayer ``` If I add -dontobfuscate, it runs smoothly Here's the class that contains that field ``` public abstract class AbstractAlarmSchedulerService extends IntentService { @Inject Lazy<AbstractAlarmSchedulerNotificationDisplayer> mNotificationDisplayer; ``` I extend from this class in my application, but it belongs to an external library. These are my dagger proguard rules, copied from https://stackoverflow.com/a/18177491/218473 ``` #Dagger -keepattributes *Annotation* -keepclassmembers,allowobfuscation class * { @javax.inject.* *; @dagger.* *; <init>(); } -keep class * extends dagger.internal.Binding -keep class * extends dagger.internal.ModuleAdapter -keep class **$$ModuleAdapter -keep class **$$InjectAdapter -keep class **$$StaticInjection -keep class dagger.* { *; } -keep class javax.inject.* { *; } -keep class * extends dagger.internal.Binding -keep class * extends dagger.internal.ModuleAdapter -keep class * extends dagger.internal.StaticInjection -keep !abstract class com.mycompany.** { *; } -keepnames class dagger.Lazy ``` I've tried keeping all classes and all members to see if that fixed anything, but the error persisted ``` -keep class * { *; } ``` com.mycompany.scheduler is an external library, while com.mycompany.myapp contains the source for the actual application. In case it's needed, here's the Module I'm using ``` @Module(injects = {AlarmIntentService.class, ReminderNotificationDisplayer.class, AlarmsBroadcastReceiver.class}) public class AndroidModule { private final AbstractMyApplication application; public AndroidModule(AbstractMyApplication application) { this.application = application; } /** * Allow the application context to be injected */ @Provides @Singleton Context provideApplicationContext() { return application; } @Provides public AlarmManager provideAlarmManager(Context context){ return (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); } @Provides @Singleton public NotificationManager provideNotificationManager(Context context){ return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); } @Provides @Singleton public AbstractAlarmSchedulerNotificationDisplayer provideNotificationDisplayer() { return new ReminderNotificationDisplayer(); } } ``` I'm using dagger & dagger-compiler 1.2.+ dependencies Thanks!

Original source

Related problems