Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
425 views
in Technique[技术] by (71.8m points)

android - Dagger + Proguard obfuscation, Errors creating object graph

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!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...