如何在3G和2G/EDGE之间切换?

4

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


这个问题不适合在StackOverflow上提问。但是你可以通过设置->移动网络->使用2G网络复选框来解决它。 - Axarydax
我正在尝试通过代码来实现它。 - senthil prabhu
你能分享一下你尝试过的内容吗? - manjusg
ConnectivityManager mgr = (ConnectivityManager)activity.getSystemService(Context.CONNECTIVITY_SERVICE); Method dataMtd = ConnectivityManager.class.getDeclaredMethod("setMobileDataEnabled", boolean.class); dataMtd.setAccessible(true); if (connectionStatus){
Log.i("数据开关 : ", "关闭数据连接 "); dataMtd.invoke(mgr, false); }else if (!connectionStatus){ Log.i("数据开关 : ", "打开数据连接 "); dataMtd.invoke(mgr, true); }
- senthil prabhu
2个回答

2
我发现了一种利用反射和系统调用命令解决这个问题的方法,并决定进行报告,尽管该线程已经过时并且存在一些注意事项:
  1. 需要root权限
  2. 可能只适用于某些ROM(在CM 12.1titan上测试过)
  3. 可能无法在所有Android版本上使用(在5.1.1上测试过)

其中许多代码是从/受到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);
}

在我的情况下,我使用第二个参数为1表示2G,10表示3G优先级来调用该方法。不同网络类型的常量可以在这里找到。
为了方便和完整性,我还会在此处复制粘贴executeCommandViaSu方法,该方法来自于ChuongPham的答案
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
据我所知,由于这是一个受限制的设置,因此无法这样做。您需要特殊权限才能更改它。请查看this帖子。
编辑:更新链接,现在可以使用。

我在你的回答中没有找到任何链接,能否请您再次发送该帖子的链接。 - senthil prabhu
谢谢。我会检查并回来,如果有任何疑问。 - senthil prabhu
是的,我理解我们需要特殊权限。您能帮我了解该过程吗? - senthil prabhu
不幸的是,没有人可以这样做,您必须自己编写定制版的Android才能开始操作。我认为这就是为什么Android市场上没有充满打开/关闭3G网络的小部件的原因。像这样的小部件会随某些手机捆绑出售,因为制造商授予其应用程序权限。 - Theblacknight

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