【问题标题】:Dagger + Proguard obfuscation, Errors creating object graphDagger + Proguard 混淆,创建对象图时出错
【发布时间】:2014-05-30 09:56:11
【问题描述】:

运行我的应用程序的混淆版本会引发以下堆栈跟踪

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

如果我添加-dontobfuscate,它运行顺利

这是包含该字段的类

public abstract class AbstractAlarmSchedulerService extends IntentService {

  @Inject
  Lazy<AbstractAlarmSchedulerNotificationDisplayer> mNotificationDisplayer;

我在我的应用程序中扩展了这个类,但它属于一个外部库。

这些是我的 dagger proguard 规则,复制自 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

我已尝试保留所有类和所有成员以查看是否解决了任何问题,但错误仍然存​​在

-keep class * { *; }

com.mycompany.scheduler 是一个外部库,而 com.mycompany.myapp 包含实际应用程序的源代码。

如果需要,这是我正在使用的模块

@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();
  }
}

我正在使用 dagger & dagger-compiler 1.2.+ 依赖项

谢谢!

【问题讨论】:

    标签: android proguard dagger


    【解决方案1】:

    Dagger 1.x 存在混淆问题。它可以使用适当的 -keep 语句进行代码收缩,但由于使用字符串键,混淆变得有问题。字符串在 proguarding 之前生成,但在 proguarding 之后被消耗,并且不与新重命名的类型对齐。

    在我们禁用反射模块适配器之前的 Dagger 1.x(大约 1.0.0)将起作用,因为纯反射会导致提供和注入一种被认为是“及时”(即在保护之后)的类型,因此被混淆了类型匹配。如果代码混淆的优先级高于性能,请考虑使用这个稍旧的版本。

    Dagger 2.x(正在进行中)没有字符串键,并导致直接的类引用,并且应该与 Proguard 很好地配合。请继续关注匕首列表和项目。我们预计 2.x 的早期版本将在此发布后的几周内下降。

    另外,更具体地说,请确保您-keepattributes Signature。您看到的具体错误是因为 JDK5+ 泛型被 proguard 剥离。一个从不注入Lazy,一个注入Lazy&lt;Foo&gt;。这将解决此特定错误,但您将遇到上述问题。

    【讨论】:

    • 感谢您的详尽回答,也非常感谢图书馆!
    【解决方案2】:

    我无法让 Dagger 1.2 与 ProGuard 一起使用,并且在 Progruard github 帐户上阅读问题我想我并不孤单 - https://github.com/square/dagger/issues/202

    但是,我已经设法让 1.0.0 版按照您上面提到的规则工作(没有 dagger-compiler!)。尽管已经很老了,但在大型 Android 应用程序中运行良好。

    【讨论】:

    • 据我所知,dagger-compiler 会从运行时移除反射,从而显着提高性能,尤其是在旧的 Android 版本上。无论如何,谢谢你的回答。
    • 我认为 1.0.1 也应该可以工作,但是 1.1.0 使用 dagger-compiler 会使其无法工作。
    猜你喜欢
    • 2013-10-07
    • 1970-01-01
    • 1970-01-01
    • 2012-01-14
    • 1970-01-01
    • 2019-07-20
    • 2013-09-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多