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

Posted

技术标签:

【中文标题】如何从 3G 和 2G/EDGE 反之切换?【英文标题】:How to switch from 3G and 2G/EDGE vice versa? 【发布时间】:2012-02-22 02:16:32 【问题描述】:

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

【问题讨论】:

这个问题不属于 ***。您可以通过设置->移动网络->使用 2G 网络复选框来完成。 我正在尝试通过代码来实现。 您可以发布您尝试过的内容吗? ConnectivityManager 经理 = (ConnectivityManager)activity.getSystemService(Context.CONNECTIVITY_SERVICE);方法 dataMtd = ConnectivityManager.class.getDeclaredMethod("setMobileDataEnabled", boolean.class); dataMtd.setAccessible(true); if (connectionStatus) Log.i("数据切换:", "关闭数据连接"); dataMtd.invoke(mgr, false); else if (!connectionStatus) Log.i("Data Switch : ", "Switching On data connection"); dataMtd.invoke(mgr, true); 【参考方案1】:

我偶然发现了一种通过反射和系统调用命令来解决这个问题的方法,并决定报告它,即使线程很旧并且有一些警告:

    需要根 Hackish 并且可能特定于 ROM(在 CM 12.1 titan 上测试) 可能不适用于所有 android 版本(在 5.1.1 上测试)

大部分代码是从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);

在我的例子中,我调用该方法,第二个参数是 1 代表 2G,10 代表 3G 偏好。不同网络类型的常量可以在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;
        
    

【讨论】:

【参考方案2】:

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

编辑:更新的链接,现在可以使用

【讨论】:

我在你的答案中没有找到任何链接,你可以再发一次帖子的链接。 谢谢。如果我有任何疑问,我会检查并回复。 是的,我知道我们需要特别许可。你能帮我完成那个程序吗? 不幸的是没有人可以,您必须旋转自己的自定义 Android 版本才能开始这样做。我认为这就是为什么 android 市场没有充满可以打开/关闭 3g 的小部件的原因。像这样的小部件与某些手机捆绑在一起,因为制造商会授予他们的应用权限。

以上是关于如何从 3G 和 2G/EDGE 反之切换?的主要内容,如果未能解决你的问题,请参考以下文章

从 WiFi 切换到 3G 时出现网络错误

如何处理 iPhone 中的网络切换?

安卓手机如何选择网络?如2G,3G,4G的切换。

将网络从 wifi 切换到 3g 时 Android/Xamarin.Android 休息客户端超时

在两个视图之间切换以及从纵向切换到横向时出现 iPad 方向问题,反之亦然

如何在单击按钮时在android中从3G切换到2G