Почему метод с логическим параметром не может быть найден с помощью отражения? - PullRequest
5 голосов
/ 02 марта 2011

Я играю с некоторыми вызовами отражения, чтобы вызвать метод, который обычно скрыт от меня.

Я знаю, что это не хорошее поведение, но, как я уже сказал, я играю.

Я использовал этот код для извлечения и вызова метода:

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 ]

18 голосов
/ 02 марта 2011

Две возможные причины этой проблемы, не могу сказать, что, не зная источника:

  • Является ли тип параметра на самом деле Boolean, а не boolean? Различные типы, потенциально разные перегруженные методы, поэтому такие литералы, как boolean.class существуют и должны использоваться здесь.
  • Метод унаследован? getDeclaredMethod() смотрит только на собственные методы класса, а не на те, которые были унаследованы. Вам придется перебирать иерархию классов, чтобы получить унаследованные методы.
7 голосов
/ 02 марта 2011

В заголовке Вопроса вы пишете boolean (нижний регистр), но в своем коде вы ищете Boolean (верхний регистр).Попробуйте это, если тип параметра boolean (примитив):

setData = ConnectivityManager.class.getDeclaredMethod(
          "setMobileDataEnabled", boolean.class);
0 голосов
/ 15 декабря 2011

Поместите соответствующие разрешения на использование в AndroidManifest.xml

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

Проблема, с которой вы столкнулись - это проблема безопасности.

0 голосов
/ 02 марта 2011

Является ли setMobileDataEnabled в ConnectivityManager или родительском классе?Глядя на getDeclaredMethod, я думаю, что он должен быть в самом классе, тогда как getMethod получает методы из всего дерева наследования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...