反射调用setMobileDataEnabled方法设置移动数据网络失败

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_15345551/article/details/52054400
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);



getDeclaredMethod通过传入的方法名和参数查找方法,这个写就能正常调用了!


注意,我验证的版本是Android4.4,最近好多哥们说其他的版本上不能用,这个应该是正常的,因为这本来就是私有的方法,所以可能会随着版本的改动做修改,这时候建议你们的做法是:

 // 取得IConnectivityManager类
            iConMgrClass = Class.forName(iConMgr.getClass().getName());
可以把这个类里面的方法都反射出来看下,找到是否有setMobileDataEnabled这个方法,如果有,肯定是传入的参数改了,反射是可以看到要传入的参数的(具体方法不会的百度),照着参数传入就可以!


有问题qq:1024883177

猜你喜欢

转载自blog.csdn.net/qq_15345551/article/details/52054400