在Android 4.4.2上以编程方式切换移动数据

时间:2014-02-02 13:36:40

标签: android android-4.4-kitkat

我一直使用此代码以编程方式启用移动数据:

ConnectivityManager conman = (ConnectivityManager) context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
@SuppressWarnings("rawtypes")
final Class conmanClass = Class.forName(conman.getClass().getName());
final Field iConnectivityManagerField = conmanClass.getDeclaredField("mService");
iConnectivityManagerField.setAccessible(true);
final Object iConnectivityManager = iConnectivityManagerField.get(conman);
@SuppressWarnings("rawtypes")
final Class iConnectivityManagerClass = Class.forName(iConnectivityManager.getClass().getName());
@SuppressWarnings("unchecked")
final Method setMobileDataEnabledMethod = iConnectivityManagerClass.getDeclaredMethod("setMobileDataEnabled", Boolean.TYPE);
setMobileDataEnabledMethod.setAccessible(true);
setMobileDataEnabledMethod.invoke(iConnectivityManager, true);

这很好用,除了现在在Android 4.4.2上,我得到了这个例外:

java.lang.NoSuchMethodException: setMobileDataEnabled [boolean]
    at  java.lang.Class.getConstructorOrMethod(Class.java:472)
    at java.lang.Class.getDeclaredMethod(Class.java:640)
    at com.test.auto3gPro.ClasseConnessione.settaConnessione(ClasseConnessione.java:48)
    at com.test.auto3gPro.receiver.ScreenBroadcastReceiver.onReceive(ScreenBroadcastReceiver.java:108)
    at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:768)
    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:5081)
    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:781)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
    at dalvik.system.NativeStart.main(Native Method)

有谁知道如何解决这个问题?

4 个答案:

答案 0 :(得分:9)

如果你正在使用cyanogenmod,那么方法setMobileDataEnabled(boolean)在setMobileDataEnabled(String,boolean)中被改变......正如你所见on this line of code

所以你可以使用标准方式,然后在NoSuchMethodException catch块中尝试这样的“cyanogenmod”方式:

Class[] cArg = new Class[2];
cArg[0] = String.class;
cArg[1] = Boolean.TYPE;
Method setMobileDataEnabledMethod;

setMobileDataEnabledMethod = iConnectivityManagerClass.getDeclaredMethod("setMobileDataEnabled", cArg);

Object[] pArg = new Object[2];
pArg[0] = getContext().getPackageName();
pArg[1] = true;
setMobileDataEnabledMethod.setAccessible(true);
setMobileDataEnabledMethod.invoke(iConnectivityManager, pArg);

我不知道其他mod是否会受到影响。

答案 1 :(得分:4)

这适用于Android 4.4.4第2版

public void onClick(View view){
    ConnectivityManager dataManager;
    dataManager  = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
    Method dataMtd = null;
    try {
        dataMtd = ConnectivityManager.class.getDeclaredMethod("setMobileDataEnabled", boolean.class);
    } catch (NoSuchMethodException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    dataMtd.setAccessible(true);
    try {
        dataMtd.invoke(dataManager, true);
    } catch (IllegalArgumentException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }   
}

反射仍适用于前沿版本

答案 2 :(得分:2)

看起来你已经发现了使用反射来玩类内部的危险。我确信这没有暴露,因为启用移动数据应该由用户而不是应用程序完成。如果你真的想继续这样做,你将不得不查看Android的新源文件,找出你可以在运行时发现的未暴露接口,并通过检查API级别来保护对此代码的调用。我不认为我会建议以编程方式更改移动数据。

答案 3 :(得分:0)

Android L已删除

setMobileDataEnabled

请改用:

TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
Method methodSet = Class.forName(tm.getClass().getName()).getDeclaredMethod( "setDataEnabled", Boolean.TYPE);
methodSet.invoke(tm,true);

确保您的清单上有此权限:

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

此权限仅适用于系统应用