2

I've used the TouchInterceptor class in the Google Music application in my application. This class allows you to drag and drop list items into different positions in the list.

The TouchInterceptor class makes a call to a method called smoothScrollBy. This method is only available in API 8+.

I want to target my application at API 7+, so I need to use reflection to execute smoothScrollBy only if it exists.

In the constructor for TouchInterceptor, I've added the following:

    Method[] ms = this.getClass().getDeclaredMethods();
    if (ms != null) {
        for (Method m : ms) {
            if (m != null && m.toGenericString().equals("smoothScrollBy")) {
                Class[] parameters = m.getParameterTypes();
                if (parameters != null && parameters.length == 1 && parameters[0].getName().equals("int")) {
                    mSmoothScrollBy = m;
                }
            }
        }
    }

This should find the smoothScrollBy method and assign it to a new member variable of TouchInterceptor called mSmoothScrollBy (Method).

I'm debugging through on an Android 2.2 (API 8) emulator and unfortunately the method is never found. My guess is getDeclaredMethods() does not return it in the array because smoothScrollBy is a method of AbsListView, which is inherited by ListView and ultimately TouchInterceptor.

I've tried casting this to AbsListView before calling getClass().getDeclaredMethods() with no success.

How can I properly get ahold of smoothScrollBy so I can invoke it when available?

Update:

I've also tried the following to no avail:

        Method test = null;
        try {
            test = this.getClass().getMethod("smoothScrollBy", new Class[] { Integer.class });
        }
        catch (NoSuchMethodException e) {

        }
Andrew
  • 20,756
  • 32
  • 99
  • 177

4 Answers4

1

It is because it is an inherited method. getDeclaredMethods() only retrieves methods declared within your class, not the methods of its superclasses. Although I have never actually done this, you should be able to call getSuperclass() until you find the class that declares the method (AbsListView) and get the method from it.

An easier answer might be just to check the version of the API though: Programmatically obtain the Android API level of a device?

Community
  • 1
  • 1
Gyan aka Gary Buyn
  • 12,242
  • 2
  • 23
  • 26
0

I'm not sure, but I think if you target your application to API 7, then the method won't be found, cause it won't exist. You can target API 8 and list in your manifest that you only require API level 7.

Kratz
  • 4,280
  • 3
  • 32
  • 55
0

Create a method called hasMethod(Class cls, String method) or similar which recursively calls itself up the inheritance hierarchy:

public boolean hasMethod(Class cls, String method) {
    // check if cls has the method, if it does return true
    // if cls == Object.class, return false
    // else, make recursive call
    return hasMethod(cls.getSuperclass(), method);
}
jches
  • 4,542
  • 24
  • 36
0

Thanks for your replies. I've solved the problem by doing the following:

    try {
        mSmoothScrollBy = this.getClass().getMethod("smoothScrollBy", new Class[] { int.class, int.class });
    }
    catch (NoSuchMethodException e) {

    }

I had the parameter list of the method I was looking for incorrect.

Andrew
  • 20,756
  • 32
  • 99
  • 177