Skip to content
This repository was archived by the owner on Apr 30, 2019. It is now read-only.
This repository was archived by the owner on Apr 30, 2019. It is now read-only.

NoSuchMethodException when registering class instances on Android 2.2 & 2.3.7 #37

Closed

Description

@klevi

Each and every time I try to register a class instance as a listener on OS versions older than Honeycomb, my app throws a NoSuchMethodException. I know that on the site it's stated that the library "is compatible with all versions of Android and has no minimum SDK requirement.", but this probably has to do something with that, since it runs perfectly on Honeycomb, ICS & Jelly Bean.

Code:

@Override
public void onResume() {
        super.onResume();
        EventBusProvider.getInstance().register(this);
}

Log:

FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to resume activity {com.app/com.uilibrary.HomeActivity}: java.lang.NoSuchMethodException
    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2241)
    at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2256)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1789)
    at android.app.ActivityThread.access$1500(ActivityThread.java:123)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:939)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:130)
    at android.app.ActivityThread.main(ActivityThread.java:3835)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:507)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:847)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:605)
    at dalvik.system.NativeStart.main(Native Method)
 Caused by: java.lang.NoSuchMethodException
    at java.lang.Class.getDeclaredMethods(Native Method)
    at java.lang.ClassCache.getDeclaredMethods(ClassCache.java:140)
    at java.lang.Class.getDeclaredMethods(Class.java:757)
    at com.squareup.otto.AnnotatedHandlerFinder.loadAnnotatedMethods(AnnotatedHandlerFinder.java:52)
    at com.squareup.otto.AnnotatedHandlerFinder.findAllProducers(AnnotatedHandlerFinder.java:116)
    at com.squareup.otto.HandlerFinder$1.findAllProducers(HandlerFinder.java:33)
    at com.squareup.otto.Bus.register(Bus.java:187)
    at com.uilibrary.HomeActivity.onResume(HomeActivity.java:218)
    at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1150)
    at android.app.Activity.performResume(Activity.java:3832)
    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2231)
    ... 12 more

Activity

  1. JakeWharton commented on Nov 12, 2012

    @JakeWharton
    Collaborator

    Er, this would indicate a seriously broken version of Dalvik since Class#getDeclaredMethods() has been available since API 1. Does this happen on emulators, phones, or both? Is the device running a custom ROM from an OEM (e.g., HTC Sense, MotoBlur, TouchWiz, etc.)?

  2. klevi commented on Nov 12, 2012

    @klevi
    Author

    1st device: LG P500 running Android OS 2.2 (this should be stock Android)
    2nd device: Orange Boston - Gigabyte G1305 running CyanogenMod 7.2 (Android 2.3.7)

    Since they are very different, the problem should be something else. Note that I'm using your ActionBarSherlock library, but that shouldn't be an issue.

    Edit 1: just checked it on a Motorola Milestone running 2.2.1 ... same problem
    Edit 2: The HomeActivity extends SherlockFragmentActivity (maybe there's something wrong when extending onResume?)

  3. swankjesse commented on Nov 12, 2012

    @swankjesse
    Contributor

    This looks a lot like the cunning android bug I encountered in August.

  4. klevi commented on Nov 13, 2012

    @klevi
    Author

    I have no listeners in xml files, and also checked the project with Lint, but there's no API call that should have any backwards compatibility problem. Any other ideas?

    Edit: I red swankjesse's post over and over, and finally managed to solve the problem. Turns out I had a widget available from API level 11 in my code. Event if it was only declared, not used within the code where the app was running on older Android versions, the app was crashing. Don't know why exactly the exception was thrown pointing to this library, but probably because of the process described by swankjesse in the blog post above.

    Thanks for the support, and sorry because of the false alarm.
    Keep up the good work!

  5. tyvsmith commented on Feb 18, 2014

    @tyvsmith

    This should be re-opened. Otto uses reflection to look for producers. If a method class takes a parameter that didn't exist on the version being tested, it'll fail.

    Caused by: java.lang.NoSuchMethodException
                at java.lang.Class.getDeclaredMethods(Native Method)
                at java.lang.ClassCache.getDeclaredMethods(ClassCache.java:140)
                at java.lang.Class.getDeclaredMethods(Class.java:757)            
                at java.lang.Class.getDeclaredMethods(Class.java:757)
                at com.squareup.otto.AnnotatedHandlerFinder.loadAnnotatedMethods(AnnotatedHandlerFinder.java:52)
                at com.squareup.otto.AnnotatedHandlerFinder.findAllProducers(AnnotatedHandlerFinder.java:119)
                at com.squareup.otto.HandlerFinder$1.findAllProducers(HandlerFinder.java:33)
                at com.squareup.otto.Bus.register(Bus.java:187)
    

    For example, assuming the containing class contains a register call, this method existing will cause Otto to fail on 2.3 (without being called).

        @TargetApi(Build.VERSION_CODES.HONEYCOMB)
        public JsonReader testMethod(JsonReader test) {
            return null;
        }
    
  6. JakeWharton commented on Feb 18, 2014

    @JakeWharton
    Collaborator

    @tyvsmith What would you expect the library to do in that case? Without a fundamental re-write we're forced to use reflection.

  7. tyvsmith commented on Feb 18, 2014

    @tyvsmith

    @JakeWharton Agreed that a fundamental re-write would resolve this, but short of that, documenting this gotcha is probably important. Aside from that, I'd experiment with catching the exception and continuing. A developer shouldn't have a method that would cause this behavior that would also be subscribing or producing on that version of Android.

  8. tyvsmith commented on Feb 19, 2014

    @tyvsmith

    The workaround we're using for now is encouraging the use of inner classes and interface implementations to subscribe and produce, thus preventing the parent from being iterated on and containing the event bus logic to a guaranteed area.

    Something like this in a base class:

        public interface EventBusMethods { }
        protected abstract Bus getEventBus();
        protected abstract EventBusMethods getEventBusMethods();
    
        public BaseClass() {
            getEventBus().register(getEventBusMethods());
        }
    
  9. added a commit that references this issue on Jan 7, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions