如何从3G和2G / EDGE切换反之亦然?

时间:2012-01-30 08:46:03

标签: android 3g-network

我正在尝试通过代码将网络首选项从3G切换到2G / EDGE,反之亦然。我可以打开和关闭移动数据连接。现在我需要知道如何通过代码在3G到2G / EDGE之间切换,反之亦然。有人可以帮我吗提前致谢。

2 个答案:

答案 0 :(得分:2)

我偶然发现了使用反射和系统调用命令解决此问题的方法,并决定报告它,即使该线程已经过时并且存在一些警告:

  1. 需要根
  2. Hackish,也许是ROM特有的(在CM 12.1 titan上测试)
  3. 可能不适用于所有Android版本(在5.1.1上测试)
  4. 许多代码都是从this answer by ChuongPham借用/启发的。

    首先,我们需要通过获取ITelephony类的声明字段的值来获取正确的事务代码。由于我怀疑该字段的名称可能会略有不同,具体取决于平台(因为我的字段名称是" TRANSACTION_setPreferredNetworkType_96"),我提供了尽可能灵活的解决方案:

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

    接下来,我们可以通过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);
    }
    

    在我的情况下,我将该方法称为2G的第2个参数为1,3G优先级为10。可以找到不同网络类型的常量here

    为了方便和完整,我还在ChuongPham's answer复制粘贴executeCommandViaSu方法:

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

答案 1 :(得分:1)

据我所知,不能这样做,因为它是受限制的设置。您需要特殊权限才能进行更改。看一下this帖子。

编辑:更新了链接,现在正在使用