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

时间:2011-03-02 11:34:49

标签: java reflection

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

我知道这不是好行为,但正如我所说的那样。

我使用此代码检索并调用方法:

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)

此输出向我显示Method在那里,我可以调用它,尽管Android健全性检查启动并禁止调用更深层次的系统方法。

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

4 个答案:

答案 0 :(得分:18)

这个问题的两个可能原因,不知道哪个不知道来源:

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

答案 1 :(得分:7)

在问题标题中,您编写boolean(小写),但在您的代码中,您搜索Boolean(大写)。如果参数类型为boolean(原始):

,请尝试此操作
setData = ConnectivityManager.class.getDeclaredMethod(
          "setMobileDataEnabled", boolean.class);

答案 2 :(得分:0)

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

答案 3 :(得分:0)

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

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

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