为什么通过反射找不到带有布尔参数的方法?
我正在尝试一些反射调用来调用通常对我隐藏的方法。
我知道这不是好行为,但正如我所说,我只是在玩玩。
我使用此代码来检索和调用该方法:
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
找不到该方法?
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 getDeclaredMethod
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
此问题的两个可能原因,在不知道来源的情况下无法说出哪一个:
Boolean
而不是boolean
吗?不同的类型,可能有不同的重载方法,这就是为什么像boolean.class
这样的文字存在并且必须在此处使用的原因。getDeclaredMethod()
仅查看类自己的方法,而不查看已继承的方法。您必须遍历类层次结构才能获取继承的方法。Two possible causes of this problem, can't say which without knowning the source:
Boolean
and notboolean
? Different types, potentially different overloaded methods, which is why literals likeboolean.class
exist and have to be used here.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.在问题标题中,您编写
boolean
(小写),但在代码中,您搜索Boolean
(大写)。如果参数类型为布尔值(原始),请尝试此操作:In the Question title, you write
boolean
(lower case), but in your code, you search forBoolean
(upper case). Try this if the parameter type isboolean
(primitive):setMobileDataEnabled
是在 ConnectivityManager 还是父类上?看看 getDeclaredMethod,我认为它需要在类本身上,而 getMethod 从整个继承树中获取方法。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.将正确的使用权限放入 AndroidManifest.xml
您遇到的问题是安全问题。
Put the proper uses permissions in the AndroidManifest.xml
The problem you are having is a security issue.