I am trying to invoke the getSelection
method of WebView
. I am trying to use the reflection APIs in Android to get the selected text.
I have extended WebView
(the new class is named MyWebView
) to add some functionality. The method getSelection
is invoked like so within MyWebView
:
for(Method m : WebView.class.getDeclaredMethods()) {
if(m.getName().equalsIgnoreCase("getSelection")) {
m.setAccessible(true);
String str;
try {
Log.v(this.toString(), "is getSelection available? " + m.getModifiers() + " " + m.isAccessible());
str = (String) m.invoke(this, new Object[] { null });
Log.v(this.toString(), "String selected = " + str);
Toast.makeText(context, str, Toast.LENGTH_LONG).show();
MyWebView
is a non-Activity class. Running the code results in the following LogCat
output:
08-16 19:15:22.745: W/System.err(23452): java.lang.IllegalArgumentException: object is not an instance of the class
08-16 19:15:22.745: W/System.err(23452): at java.lang.reflect.Method.invokeNative(Native Method)
08-16 19:15:22.745: W/System.err(23452): at java.lang.reflect.Method.invoke(Method.java:507)
08-16 19:15:22.745: W/System.err(23452): at com.englishhelper.bluebottle.EHWebView$3.onTouch(EHWebView.java:210)
08-16 19:15:22.745: W/System.err(23452): at android.view.View.dispatchTouchEvent(View.java:3934)
08-16 19:15:22.745: W/System.err(23452): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:903)
08-16 19:15:22.745: W/System.err(23452): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942)
08-16 19:15:22.745: W/System.err(23452): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942)
08-16 19:15:22.745: W/System.err(23452): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942)
08-16 19:15:22.745: W/System.err(23452): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942)
08-16 19:15:22.745: W/System.err(23452): at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1730)
08-16 19:15:22.745: W/System.err(23452): at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1142)
08-16 19:15:22.745: W/System.err(23452): at android.app.Activity.dispatchTouchEvent(Activity.java:2102)
08-16 19:15:22.745: W/System.err(23452): at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1714)
08-16 19:15:22.745: W/System.err(23452): at android.view.ViewRoot.deliverPointerEvent(ViewRoot.java:2218)
08-16 19:15:22.745: W/System.err(23452): at android.view.ViewRoot.handleMessage(ViewRoot.java:1889)
08-16 19:15:22.745: W/System.err(23452): at android.os.Handler.dispatchMessage(Handler.java:99)
08-16 19:15:22.745: W/System.err(23452): at android.os.Looper.loop(Looper.java:123)
08-16 19:15:22.745: W/System.err(23452): at android.app.ActivityThread.main(ActivityThread.java:3691)
08-16 19:15:22.745: W/System.err(23452): at java.lang.reflect.Method.invokeNative(Native Method)
08-16 19:15:22.745: W/System.err(23452): at java.lang.reflect.Method.invoke(Method.java:507)
08-16 19:15:22.745: W/System.err(23452): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:847)
08-16 19:15:22.745: W/System.err(23452): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:605)
08-16 19:15:22.745: W/System.err(23452): at dalvik.system.NativeStart.main(Native Method)
My question is:
1. The invoke
method in the Reflection API requires that I pass the object of the class on which I intend to call the method on as the first argument. In this case, it would be an object of class MyWebView
. How do I call invoke
with an object of type MyWebView
?
2. The same code works well in a case where MyWebView
is part of the Activity
class.
The exception shows that you are inside of an anonymous inner class. The problem is that you are accidentally passing the instance of the inner class instead of the instance of
EHWebView
.You can tell that you are inside of an inner class because after the normal class name
EHWebView
, you see a$3
, which simply refers to the 3rd anonymous inner class ofEHWebView
. Here is the relevant part of the stack trace you posed:Typically, anonymous inner classes are event handlers or runnables. They appear often and many people are not even aware they are using them.
You are passing
this
to theinvoke()
method. Inside of an inner class,this
refers to the instance of that inner class instead of the instance of the outer classEHWebView
.To solve the problem, pass the reference of the outer class by removing
this
an instead usingEHWebView.this
: