9

I've always used this code to enable mobile data programmatically:

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);

This worked well, except now on Android 4.4.2 where I get this exception:

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)

Does anyone know how to fix this?

Paul Lammertsma
  • 37,593
  • 16
  • 136
  • 187
Slv3r
  • 479
  • 1
  • 5
  • 15

4 Answers4

9

If you are using cyanogenmod the method setMobileDataEnabled(boolean) is changed in setMobileDataEnabled(String, boolean)...as you can see on this line of code.

So you can use the standard way and then in the NoSuchMethodException catch block try the "cyanogenmod" way like this:

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);

I don't know if other mods are affected.

hichris123
  • 10,145
  • 15
  • 56
  • 70
4

This worked for me on 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();
    }   
}

Reflection still works on the bleeding edge versions

2

Looks like you've discovered the danger of using reflection to play with internals of classes. I'm sure this wasn't exposed because enabling mobile data should be done by the user rather than by an application. If you really want to keep doing this, you'll have to look into the new source files of Android to find out the unexposed interfaces that you can discover at runtime and guard calls to this code by checks on the API level. I don't think I'd recommend programmatically changing mobile data though.

frenziedherring
  • 2,225
  • 2
  • 15
  • 23
0

setMobileDataEnabled has been removed in Android L.

Use this instead:

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

Make sure you have this permission on your manifest:

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

This permission is for System apps only

msysmilu
  • 2,015
  • 23
  • 24