Why can a method with a boolean parameter not be found via reflection?
I'm playing around with some reflection calls to call a method that is normally hidden from me.
I know that this isn't good behaviour but as I said im playing around.
I used this code to retrieve and invoke the method:
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
setData = ConnectivityManager.class.getDeclaredMethod("setMobileDataEnabled", Boolean.class);
setData.setAccessible(true);
setData.invoke(cm, false);
This gives me this Exception:
03-02 12:21:40.411: ERROR/test(1052): java.lang.NoSuchMethodException: setMobileDataEnabled
03-02 12:21:40.411: ERROR/test(1052): at java.lang.ClassCache.findMethodByName(ClassCache.java:308)
03-02 12:21:40.411: ERROR/test(1052): at java.lang.Class.getDeclaredMethod(Class.java:748)
Then i tried to see if the method is declared in the class and tried this to find all methods and invoke the wanted method:
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
Method[] methods = cm.getClass().getMethods();
for (Method method : methods) {
Log.d(Test.class.getSimpleName(), "Method name is: " + method.getName());
if (method.getName().equals("setMobileDataEnabled")) {
Log.d(Test.class.getSimpleName(), "Found method calling");
method.setAccessible(true);
method.invoke(cm, false);
}
}
This gives me the following output:
03-02 12:19:41.851: DEBUG/Test(980): Method name is: getActiveNetworkInfo
03-02 12:19:41.851: DEBUG/Test(980): Method name is: getAllNetworkInfo
03-02 12:19:41.851: DEBUG/Test(980): Method name is: getBackgroundDataSetting
03-02 12:19:41.851: DEBUG/Test(980): Method name is: getLastTetherError
03-02 12:19:41.861: DEBUG/Test(980): Method name is: getMobileDataEnabled
03-02 12:19:41.861: DEBUG/Test(980): Method name is: getNetworkInfo
03-02 12:19:41.861: DEBUG/Test(980): Method name is: getNetworkPreference
03-02 12:19:41.861: DEBUG/Test(980): Method name is: getTetherableIfaces
03-02 12:19:41.861: DEBUG/Test(980): Method name is: getTetherableUsbRegexs
03-02 12:19:41.861: DEBUG/Test(980): Method name is: getTetherableWifiRegexs
03-02 12:19:41.861: DEBUG/Test(980): Method name is: getTetheredIfaces
03-02 12:19:41.871: DEBUG/Test(980): Method name is: getTetheringErroredIfaces
03-02 12:19:41.871: DEBUG/Test(980): Method name is: isTetheringSupported
03-02 12:19:41.871: DEBUG/Test(980): Method name is: requestRouteToHost
03-02 12:19:41.871: DEBUG/Test(980): Method name is: setBackgroundDataSetting
03-02 12:19:41.871: DEBUG/Test(980): Method name is: setMobileDataEnabled
03-02 12:19:41.871: DEBUG/Test(980): Found method calling
03-02 12:19:41.871: DEBUG/ConnectivityService(127): setMobileDataEnabled(false)
03-02 12:19:41.891: DEBUG/ConnectivityService(127): getMobileDataEnabled returning true
03-02 12:19:41.931: ERROR/Test(980): InvocationTargetException
03-02 12:19:41.931: ERROR/Test(980): java.lang.reflect.InvocationTargetException
03-02 12:19:41.931: ERROR/Test(980): at android.net.ConnectivityManager.setMobileDataEnabled(ConnectivityManager.java:379)
03-02 12:19:41.931: ERROR/Test(980): at java.lang.reflect.Method.invokeNative(Native Method)
03-02 12:19:41.931: ERROR/Test(980): at java.lang.reflect.Method.invoke(Method.java:521)
03-02 12:19:41.931: ERROR/Test(980): at Test(Test.java:84)
This output shows me that the Method
is there and I can call it despite the fact that the Android sanity check kicks in and forbids the calling of the deeper system methods.
Why is it that the method is not found via getDeclared开发者_运维技巧Method
?
Two possible causes of this problem, can't say which without knowning the source:
- Is the parameter type actually
Boolean
and notboolean
? Different types, potentially different overloaded methods, which is why literals likeboolean.class
exist and have to be used here. - Is the method inherited?
getDeclaredMethod()
only looks at the class's own methods, not those that have been inherited. You'll have to iterate through the class hierarchy to get inherited methods.
In the Question title, you write boolean
(lower case), but in your code, you search for Boolean
(upper case). Try this if the parameter type is boolean
(primitive):
setData = ConnectivityManager.class.getDeclaredMethod(
"setMobileDataEnabled", boolean.class);
Is setMobileDataEnabled
on ConnectivityManager or a parent class? Looking at getDeclaredMethod, I think it needs to be on the class itself, whereas getMethod gets methods from the entire inheritance tree.
Put the proper uses permissions in the AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
The problem you are having is a security issue.
精彩评论