4

I am trying to access a method using reflection and one of the parameter is a callback. The callback type is generic interface of different class type. These classes are @SystemApi can be accessed by reflection. Here is the class I am working with above sayings.

Below is my sample code :

 String sClassName = "android.telephony.euicc.EuiccCardManager";
 Class classToInvestigate = Class.forName(sClassName);
 Class interfaceclass = classToInvestigate.getClasses()[0]; //android.telephony.euicc.EuiccCardManager.ResultCallback

 Method getallprofiles = classToInvestigate.getDeclaredMethod("requestAllProfiles", String.class,Executor.class, interfaceclass);
 getallprofiles.invoke(null,getEid(), AsyncTask.THREAD_POOL_EXECUTOR,null);

In the above invoke signature as a last parameter I need to pass the callback created using reflection and which is equivalent or similar to the below callback sample.

ResultCallback<EuiccProfileInfo[]> callback =
new ResultCallback<EuiccProfileInfo[]>() {
@Override
public void onComplete(int resultCode, EuiccProfileInfo[] result) { }
};
  • The above ResultCallback interface can be found in the same class link I provided above and the same instance in interfaceclass field above.
  • EuiccProfileInfo is the another class need to access from reflection because it is @SystemApi

I have failed/stuck to translate the above callback logic with reflection.Anyone can help me on this?

3
  • Have you looked into stackoverflow.com/questions/1082850/… ? Commented Jul 18, 2018 at 9:04
  • @GennadiiSaprykin yes but in my case the interface itself I need to have in reflection. Commented Jul 18, 2018 at 9:22
  • Did my answer help? or you still need something here? Commented Jul 19, 2018 at 10:40

1 Answer 1

4

Seems that you need to create a proxy class:

// that class you don't have access too. imagine that it is not here, it is just to show example signature of method we want to run.
interface Callback {
    void run();
}

public static void main(String[] args) throws Exception {
    Class<?> callbackClass = Class.forName("package.Callback");
    Callback callback = Proxy.newProxyInstance(Main.class.getClassLoader(), new Class[]{callbackClass}, new CallbackInvocationHandler(() -> {
        System.out.println("callback");
    }));
    callbackClass.getMethod("run").invoke(callback); // works!
}

static class CallbackInvocationHandler implements InvocationHandler {
    private final Runnable myCallback;

    CallbackInvocationHandler(Runnable myCallback) {
        this.myCallback = myCallback;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (method.getName().equals("toString") && (method.getParameterCount() == 0)) {
            // just random implementation
            return proxy.getClass() + "@" + Integer.toHexString(System.identityHashCode(proxy));
        }
        if (method.getName().equals("hashCode") && (method.getParameterCount() == 0)) {
            return System.identityHashCode(proxy);
        }
        if (method.getName().equals("equals") && (method.getParameterCount() == 1) && (method.getParameterTypes()[0] == Object.class)) {
            return proxy == args[0];
        }
        if (method.getName().equals("run") && (method.getParameterCount() == 0)) {
            // do what you want.
            myCallback.run();
            return null;
        }
        throw new IllegalStateException("Method not implemented: " + method);
    }
}

But if you really need to use something like that - there are huge chances you are doing something wrong, can't you just add dependency on that project? But you should not depend on system classes too.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for the answer..I took this as a base idea to write for my requirement. Proxy.newProxyInstance(interfaceclass.getClassLoader(), new Class[]{interfaceclass}, new ProxyListener()); public class ProxyListener implements java.lang.reflect.InvocationHandler { private static final Logger LOGGER = LoggerFactory.getLogger(ProxyListener.class); @Override public Object invoke(Object o, Method method, Object[] objects) throws Throwable { return null; }}
Callback in your example represents the hidden interface that you want to implement, right? Which you would get through Class<?> cCallback = Class.for("..."). However, how are you supposed to do the cast in the end if you don't have the type itself. If you meant it in the way that you declare the hidden interface yourself as in your example, then still the proxy returned is null.
@phoebus OP wanted to pass this callback using reflections to other method - so all he needs is an Object I used real type just to show working example. Also you can call this method via reflections if you need.
I've created another question so you can see what exactly I want to achieve and how I want to use it: stackoverflow.com/questions/51659917/…
@phoebus I modified my answer so it does not reference that example calback class directly

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.