Java 为什么不能通过反射找到带有布尔参数的方法?

Java 为什么不能通过反射找到带有布尔参数的方法?,java,reflection,Java,Reflection,我正在玩一些反射调用来调用一个通常对我隐藏的方法 我知道这不是好行为,但正如我所说的,我只是在胡闹 我使用以下代码检索并调用该方法: ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); setData = ConnectivityManager.class.getDeclaredMethod("setMobileDataEnabled", B

我正在玩一些反射调用来调用一个通常对我隐藏的方法

我知道这不是好行为,但正如我所说的,我只是在胡闹

我使用以下代码检索并调用该方法:

ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

setData = ConnectivityManager.class.getDeclaredMethod("setMobileDataEnabled", Boolean.class);
setData.setAccessible(true);
setData.invoke(cm, false);
这给了我一个例外:

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)
然后我尝试查看该方法是否在类中声明,并尝试查找所有方法并调用所需的方法:

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);
   }
}
这为我提供了以下输出:

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)
这个输出告诉我,
方法
就在那里,我可以调用它,尽管事实上Android健全性检查已经开始,并且禁止调用更深层的系统方法


为什么通过
getDeclaredMethod
找不到该方法?

是在ConnectionManager或父类上设置的
setMobileDataEnabled
?看看getDeclaredMethod,我认为它需要在类本身上,而getMethod从整个继承树中获取方法。

这个问题的两个可能原因,在不知道源代码的情况下无法确定:

  • 参数类型实际上是
    Boolean
    而不是
    Boolean
    ?不同的类型,可能不同的重载方法,这就是为什么像
    boolean.class
    这样的文本存在并且必须在这里使用
  • 这个方法是继承的吗
    getDeclaredMethod()
    只查看类自己的方法,而不是继承的方法。您必须遍历类层次结构才能获得继承的方法

在问题标题中,您写的是
布尔值
(小写),但在代码中,您搜索的是
布尔值
(大写)。如果参数类型为
布尔值
(原语),请尝试此操作:


在AndroidManifest.xml中放置正确的使用权限

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />


您遇到的问题是安全问题。

InvocationTargetException
包装“真实”异常,您需要向我们显示整个堆栈跟踪。堆栈跟踪不相关,它只显示找到并调用了该方法,请尝试传递boolean.class而不是boolean.classI。但随你的便。我在2.2.1上得到了InvocationTargetException,因为未授予权限写入的SecurityException\u SECURE\u设置您是对的,我使用boolean.class看起来太不自然了,我甚至没有尝试。参数为布尔值,反射中的自动装箱不适用;)
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />