在Android 4.4.2上编程实现移动数据的开关切换

9

我一直使用这段代码来在程序中启用移动数据:

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个回答

9
如果您使用的是Cyanogenmod操作系统,setMobileDataEnabled(boolean)方法已经改成了setMobileDataEnabled(String, boolean)…您可以在这一行代码中查看。
因此您可以按照标准方式进行操作,如果在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);

我不知道其他模组是否受到影响。



4

这个方法适用于我在Android 4.4.4 release 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();
    }   
}

反射在最新版本中仍然有效。


在Android 4.1.1上抛出安全异常。 - Muhammad Babar
在AndroidManifest.xml中添加<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />后,它可以在4.4.4上为我工作。 - bmaupin

2

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


它可以与Tasker或Locale一起使用,非常有用。 - Hugo Gresse

0

setMobileDataEnabled在Android L中已被移除。

请改用以下方式:

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"/>

此权限仅适用于系统应用程序


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接