版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
Android编程在代码中打开移动网络,网上好多人都说这种方法可以,但是我用的时候就报错了:
java.lang.NoSuchMethodException: setMobileDataEnabled [boolean]
at java.lang.Class.getConstructorOrMethod(Class.java:472)
at java.lang.Class.getDeclaredMethod(Class.java:640)
at cn.basewin.pos.SystemSetActivity$override.toggleMobileData(SystemSetActivity.java:184)
at cn.basewin.pos.SystemSetActivity$override.onClick(SystemSetActivity.java:143)
at cn.basewin.pos.SystemSetActivity$override.access$dispatch(SystemSetActivity.java)
at cn.basewin.pos.SystemSetActivity.onClick(SystemSetActivity.java:0)
at android.view.View.performClick(View.java:4438)
at android.widget.CompoundButton.performClick(CompoundButton.java:100)
at android.view.View$PerformClick.run(View.java:18439)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5069)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
at dalvik.system.NativeStart.main(Native Method)
/**
* 移动网络开关
*/
private void toggleMobileData(Context context, boolean enabled) {
ConnectivityManager conMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
Class<?> conMgrClass = null; // ConnectivityManager类
Field iConMgrField = null; // ConnectivityManager类中的字段
Object iConMgr = null; // IConnectivityManager类的引用
Class<?> iConMgrClass = null; // IConnectivityManager类
Method setMobileDataEnabledMethod = null; // setMobileDataEnabled方法
try {
// 取得ConnectivityManager类
conMgrClass = Class.forName(conMgr.getClass().getName());
// 取得ConnectivityManager类中的对象mService
iConMgrField = conMgrClass.getDeclaredField("mService");
// 设置mService可访问
iConMgrField.setAccessible(true);
// 取得mService的实例化类IConnectivityManager
iConMgr = iConMgrField.get(conMgr);
// 取得IConnectivityManager类
iConMgrClass = Class.forName(iConMgr.getClass().getName());
// 取得IConnectivityManager类中的setMobileDataEnabled(boolean)方法
setMobileDataEnabledMethod = iConMgrClass.getDeclaredMethod("setMobileDataEnabled", Boolean.TYPE);
// 设置setMobileDataEnabled方法可访问
setMobileDataEnabledMethod.setAccessible(true);
// 调用setMobileDataEnabled方法
setMobileDataEnabledMethod.invoke(iConMgr, enabled);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
从报错信息是提示找不到方法,于是我用反射的方法查看这个方法传入参数的形式,一看吓一跳,这个方法不只一个参数,需要两个参数
setMobileDataEnabled(String packageName, boolean enable)//packageName为当前包名
可能是Android的版本不同导致的setMobileDataEnabled方法改变了
所以解决方法如下:
两行红的代码分别改为:
setMobileDataEnabledMethod = iConMgrClass.getDeclaredMethod("setMobileDataEnabled",String.class,boolean.class);
setMobileDataEnabledMethod.invoke(iConMgr,getPackageName() ,enabled);
java.lang.NoSuchMethodException: setMobileDataEnabled [boolean]
at java.lang.Class.getConstructorOrMethod(Class.java:472)
at java.lang.Class.getDeclaredMethod(Class.java:640)
at cn.basewin.pos.SystemSetActivity$override.toggleMobileData(SystemSetActivity.java:184)
at cn.basewin.pos.SystemSetActivity$override.onClick(SystemSetActivity.java:143)
at cn.basewin.pos.SystemSetActivity$override.access$dispatch(SystemSetActivity.java)
at cn.basewin.pos.SystemSetActivity.onClick(SystemSetActivity.java:0)
at android.view.View.performClick(View.java:4438)
at android.widget.CompoundButton.performClick(CompoundButton.java:100)
at android.view.View$PerformClick.run(View.java:18439)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5069)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
at dalvik.system.NativeStart.main(Native Method)
/**
* 移动网络开关
*/
private void toggleMobileData(Context context, boolean enabled) {
ConnectivityManager conMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
Class<?> conMgrClass = null; // ConnectivityManager类
Field iConMgrField = null; // ConnectivityManager类中的字段
Object iConMgr = null; // IConnectivityManager类的引用
Class<?> iConMgrClass = null; // IConnectivityManager类
Method setMobileDataEnabledMethod = null; // setMobileDataEnabled方法
try {
// 取得ConnectivityManager类
conMgrClass = Class.forName(conMgr.getClass().getName());
// 取得ConnectivityManager类中的对象mService
iConMgrField = conMgrClass.getDeclaredField("mService");
// 设置mService可访问
iConMgrField.setAccessible(true);
// 取得mService的实例化类IConnectivityManager
iConMgr = iConMgrField.get(conMgr);
// 取得IConnectivityManager类
iConMgrClass = Class.forName(iConMgr.getClass().getName());
// 取得IConnectivityManager类中的setMobileDataEnabled(boolean)方法
setMobileDataEnabledMethod = iConMgrClass.getDeclaredMethod("setMobileDataEnabled", Boolean.TYPE);
// 设置setMobileDataEnabled方法可访问
setMobileDataEnabledMethod.setAccessible(true);
// 调用setMobileDataEnabled方法
setMobileDataEnabledMethod.invoke(iConMgr, enabled);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
从报错信息是提示找不到方法,于是我用反射的方法查看这个方法传入参数的形式,一看吓一跳,这个方法不只一个参数,需要两个参数
setMobileDataEnabled(String packageName, boolean enable)//packageName为当前包名
可能是Android的版本不同导致的setMobileDataEnabled方法改变了
所以解决方法如下:
两行红的代码分别改为:
setMobileDataEnabledMethod = iConMgrClass.getDeclaredMethod("setMobileDataEnabled",String.class,boolean.class);
setMobileDataEnabledMethod.invoke(iConMgr,getPackageName() ,enabled);
getDeclaredMethod通过传入的方法名和参数查找方法,这个写就能正常调用了!
注意,我验证的版本是Android4.4,最近好多哥们说其他的版本上不能用,这个应该是正常的,因为这本来就是私有的方法,所以可能会随着版本的改动做修改,这时候建议你们的做法是:
// 取得IConnectivityManager类
iConMgrClass = Class.forName(iConMgr.getClass().getName());
可以把这个类里面的方法都反射出来看下,找到是否有setMobileDataEnabled这个方法,如果有,肯定是传入的参数改了,反射是可以看到要传入的参数的(具体方法不会的百度),照着参数传入就可以!
iConMgrClass = Class.forName(iConMgr.getClass().getName());
可以把这个类里面的方法都反射出来看下,找到是否有setMobileDataEnabled这个方法,如果有,肯定是传入的参数改了,反射是可以看到要传入的参数的(具体方法不会的百度),照着参数传入就可以!
有问题qq:1024883177