Как переключиться с 3G и 2G / EDGE наоборот? - PullRequest
4 голосов
/ 30 января 2012

Я пытаюсь переключить настройку сети с 3G на 2G / EDGE через код и наоборот.Я могу включать и выключать мобильное соединение для передачи данных.Теперь мне нужно знать, как переключаться с 3G на 2G / EDGE и наоборот через код.Может ли кто-нибудь помочь мне здесь.Заранее спасибо.

Ответы [ 2 ]

2 голосов
/ 29 июля 2015

Я наткнулся на способ решения этой проблемы с помощью команд отражения и системного вызова и решил сообщить об этом, даже если поток старый и есть некоторые предостережения:

  1. Требуется рут
  2. Взломанный и, возможно, специфичный для ПЗУ (протестирован на титане CM 12.1)
  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 голос
/ 30 января 2012

Насколько я знаю, это невозможно сделать, так как это ограниченная настройка.Вам нужно специальное разрешение, чтобы изменить его.Взгляните на эту запись.

редактировать: обновленная ссылка, работает сейчас

...