AndroidAnnotations and EventBus

4.1k views Asked by At

I have an annotated Activity in a library, which is a subscriber to an EventBus event from the same library. It looks something like this, greatly simplified:

@EActivity(resName = "activity_foo")
public class Foo extends Activity {

    public void onEvent(BarEvent event){
        doSomething();
    }
}

It should work according to this:

http://timnew.me/blog/2014/09/14/otto-and-android-annotations-compatibility-issue-analysis/

But in fact it returns with this error:

Unable to start activity ... de.greenrobot.event.EventBusException: Subscriber class com.foo.bar.activities.Foo_ has no public methods called onEvent

It seems EventBus doesn't look in the parent class. I guess the @Subscribe annotation everybody is talking about is only in Guava and Otto, but not in EventBus. Nobody is talking about compatibility problems between AA and Eventbus on the net, so I must be missing something.

How can I make this work?

EventBus: 2.4

AA: 3.2

EDIT:

After WonderCsabo's answer I updated EventBus to 3.0 beta (including Subscribe annotations) and AA to 3.3.1 and the problem is gone, but there is another one:

   java.lang.NoSuchFieldError
            at libcore.reflect.AnnotationAccess.decodeValue(AnnotationAccess.java:688)
            at libcore.reflect.AnnotationAccess.getDefaultValue(AnnotationAccess.java:361)
            at java.lang.reflect.Method.getDefaultValue(Method.java:327)
            at libcore.reflect.AnnotationFactory.getElementsDescription(AnnotationFactory.java:75)
            at libcore.reflect.AnnotationFactory.<init>(AnnotationFactory.java:112)
            at libcore.reflect.AnnotationFactory.createAnnotation(AnnotationFactory.java:94)
            at libcore.reflect.AnnotationAccess.toAnnotationInstance(AnnotationAccess.java:666)
            at libcore.reflect.AnnotationAccess.toAnnotationInstance(AnnotationAccess.java:641)
            at libcore.reflect.AnnotationAccess.getDeclaredAnnotation(AnnotationAccess.java:170)
            at java.lang.reflect.Method.getAnnotation(Method.java:301)
            at de.greenrobot.event.n.b(SourceFile:133)
            at de.greenrobot.event.n.a(SourceFile:79)
            at de.greenrobot.event.c.a(SourceFile:135)
            at com.babestudios.lib.lq.activities.f.onStart(SourceFile:515)
            at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1236)
            at android.app.Activity.performStart(Activity.java:6006)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2288)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
            at android.app.ActivityThread.access$800(ActivityThread.java:151)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5254)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
     Caused by: java.lang.NoSuchFieldException: PostThread
            at java.lang.Class.getDeclaredField(Class.java:890)
            at libcore.reflect.AnnotationAccess.decodeValue(AnnotationAccess.java:685)
            at libcore.reflect.AnnotationAccess.getDefaultValue(AnnotationAccess.java:361)
            at java.lang.reflect.Method.getDefaultValue(Method.java:327)
            at libcore.reflect.AnnotationFactory.getElementsDescription(AnnotationFactory.java:75)
            at libcore.reflect.AnnotationFactory.<init>(AnnotationFactory.java:112)
            at libcore.reflect.AnnotationFactory.createAnnotation(AnnotationFactory.java:94)
            at libcore.reflect.AnnotationAccess.toAnnotationInstance(AnnotationAccess.java:666)
            at libcore.reflect.AnnotationAccess.toAnnotationInstance(AnnotationAccess.java:641)
            at libcore.reflect.AnnotationAccess.getDeclaredAnnotation(AnnotationAccess.java:170)
            at java.lang.reflect.Method.getAnnotation(Method.java:301)
            at de.greenrobot.event.n.b(SourceFile:133)
            at de.greenrobot.event.n.a(SourceFile:79)
            at de.greenrobot.event.c.a(SourceFile:135)
            at com.babestudios.lib.lq.activities.f.onStart(SourceFile:515)
            at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1236)
            at android.app.Activity.performStart(Activity.java:6006)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2288)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
            at android.app.ActivityThread.access$800(ActivityThread.java:151)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5254)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

And I noticed that both problems (the missing onEvent and now the PostThread is only a problem on the release version. I use ProGuard with the recommended exceptions for EventBus and AA).

EDIT 2:

I added

-keep class de.greenrobot.** {*;}

and it seems to be working.

4

There are 4 answers

0
WonderCsabo On BEST ANSWER

You have three options:

  • Use Otto. It also has the same problem what you faced with EventBus, however AndroidAnnotations has specific Otto integration which solves that problem.
  • If you want to stick with EventBus, you can try out the experimental version, which does not has the issue as 2.4.0. It is also nicer as it is based on annotations instead of the method naming, not speaking of the huge performance boost by the optional EventBus annotation processor. But it is still in beta.
  • Or you can use EventBus 2.3.0, which does not have the problem what you have with 2.4.0.

By the way, you should update to the latest AndroidAnnotations, 3.3.1.

0
Alessio On

In case someone still faces this error, with EventBus 3.0 the package was renamed (org instead of de, and eventbus instead of event), so the proper proguard configuration is:

## GreenRobot EventBus specific rules ##
# http://greenrobot.org/eventbus/documentation/proguard/

-keepattributes *Annotation*

-keepclassmembers class ** {
    @org.greenrobot.eventbus.Subscribe <methods>;
}

-keep enum org.greenrobot.eventbus.ThreadMode { *; }

# Only required if you use AsyncExecutor
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
    <init>(java.lang.Throwable);
}

as documented in their site

0
deive On

I have EventBus Annotations working with:

# Ensure annotations are kept for runtime use.
-keepattributes *Annotation*
# Don't remove any GreenRobot classes
-keep class de.greenrobot.** {*;}
# Don't remove any methods that have the @Subscribe annotation
-keepclassmembers class ** {
    @de.greenrobot.event.Subscribe <methods>;
}

Note that this also ensures that your method names still get obfuscated.

0
cybergen On

UPDATE

It seems this is not the right answer. The exception is thrown anyway.

Original Answer

As of EventBus 3 you can disable the subscriber exception by calling throwSubscriberException(false).

By calling this in your application class you can disable this exception for your default event bus.

EventBus.builder().throwSubscriberException(false).installDefaultEventBus();