4

I am trying to switch the network preference from 3G to 2G/EDGE through code and vice versa. I can able to switch on and off the mobile data connection. Now i need know how to switch between 3G to 2G/EDGE and vice versa through code. can somebody help me here. Thanks in advance.

senthil prabhu
  • 408
  • 1
  • 5
  • 12
  • this question doesn't belong on StackOverflow. You can do it with Settings->Mobile Networks->Use 2G networks checkbox thoug. – Axarydax Jan 30 '12 at 08:48
  • I am trying to do it through code. – senthil prabhu Jan 30 '12 at 08:49
  • Can you post what you have tried? – manjusg Jan 30 '12 at 09:08
  • ConnectivityManager mgr = (ConnectivityManager)activity.getSystemService(Context.CONNECTIVITY_SERVICE); Method dataMtd = ConnectivityManager.class.getDeclaredMethod("setMobileDataEnabled", boolean.class); dataMtd.setAccessible(true); if (connectionStatus){ Log.i("Data Switch : ", "Switching Off data connection "); dataMtd.invoke(mgr, false); }else if (!connectionStatus){ Log.i("Data Switch : ", "Switching On data connection "); dataMtd.invoke(mgr, true); } – senthil prabhu Jan 30 '12 at 09:38

2 Answers2

2

I've stumbled upon a way to solve this with reflection and system call commands, and decided to report it even though the thread is old and there are some caveats:

  1. Root required
  2. Hackish and maybe ROM-specific (tested on CM 12.1 titan)
  3. Probably not working on all android versions (tested on 5.1.1)

Much of the code is borrowed from / inspired by this answer by ChuongPham.

First we need to get the correct transaction code by getting the value of a declared field of the ITelephony class. Since I suspect the name of the field might be slightly different depending on the platform (for mine the field name is "TRANSACTION_setPreferredNetworkType_96"), I provide a solution that is as flexible as possible:

private static String get3gTransactionCode(Context context) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException {
    final TelephonyManager mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
    final Class<?> mTelephonyClass = Class.forName(mTelephonyManager.getClass().getName());
    final Method mTelephonyMethod = mTelephonyClass.getDeclaredMethod("getITelephony");
    mTelephonyMethod.setAccessible(true);
    final Object mTelephonyStub = mTelephonyMethod.invoke(mTelephonyManager);
    final Class<?> mTelephonyStubClass = Class.forName(mTelephonyStub.getClass().getName());
    final Class<?> mClass = mTelephonyStubClass.getDeclaringClass();
    for (Field f:mClass.getDeclaredFields()) {
        if (f.getName().contains("setPreferredNetworkType")) {
            final Field field = mClass.getDeclaredField(f.getName());
            field.setAccessible(true);
            return String.valueOf(field.getInt(null));
        }
    }
    throw new NoSuchFieldException();
}

Next we can use the transaction code in a system call via su:

private static void setPreferredNetworkType(Context context, int preferredType) throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException, IllegalAccessException, InvocationTargetException {
    String transactionCode = get3gTransactionCode(context);
    String command = "service call phone " + transactionCode + " i32 " + preferredType;
    executeCommandViaSu(context, "-c", command);
}

In my case, I call that method with the 2nd parameter being 1 for 2G, and 10 for 3G preference. The constants for different network types can be found here.

For convenience and completeness I also copy-paste the executeCommandViaSu method from ChuongPham's answer here:

private static void executeCommandViaSu(Context context, String option, String command) {
    boolean success = false;
    String su = "su";
    for (int i=0; i < 3; i++) {
        // Default "su" command executed successfully, then quit.
        if (success) {
            break;
        }
        // Else, execute other "su" commands.
        if (i == 1) {
            su = "/system/xbin/su";
        } else if (i == 2) {
            su = "/system/bin/su";
        }
        try {
            // Execute command as "su".
            Runtime.getRuntime().exec(new String[]{su, option, command});
        } catch (IOException e) {
            success = false;
            // Oops! Cannot execute `su` for some reason.
            // Log error here.
        } finally {
            success = true;
        }
    }
}
Community
  • 1
  • 1
pulce
  • 46
  • 7
1

As far as I know cannot do this as it is a restricted setting. You need a special permission, to change it. Take a look at this post.

edit: Updated link, working now

Theblacknight
  • 575
  • 5
  • 12
  • I don't find any link in your answer can u please send the link of the post one more time. – senthil prabhu Jan 30 '12 at 09:42
  • Thank you. I will check and get back to if i have any doubts. – senthil prabhu Jan 30 '12 at 09:50
  • Yes i understand that we need special permission. Can u help me with that procedure. – senthil prabhu Jan 31 '12 at 11:10
  • Unfortunately no one can, you would have to spin your own custom version of Android to start doing that. I would think that this is why the android market isn't full of widgets that turn 3g on/off. Widgets like this come bundled with certain phones, because the manufacturers grant their apps the permission. – Theblacknight Jan 31 '12 at 13:08