Обнаружение настройки "использовать только сети 2G"

Есть ли способ вернуть значение настройки мобильной сети Android для "использовать только сети 2G"?

Разрабатываемое приложение измеряет скорость интернета в определенном месте, но для того, чтобы это было актуально, оно должно знать, намеренно ли пользователь ограничивает мобильный интернет до 2G.

Я взглянул на ConnectivityManager, но он предоставляет только информацию о фоновых настройках данных или всех сетях. Итерация по ним показывает, что, несмотря на то, что настройка включена, HSPA и UMTS возвращают true за isAvailable():

for (NetworkInfo netInfo : cm.getAllNetworkInfo()) {
    Log.i(TAG, netInfo.getSubtypeName() + ": " + netInfo.isAvailable());
}

Единственный намек, который я нашел среди всего этого, это то, что netInfo.getReason() возвращает "connectionDisabled" на HSPA и UMTS, когда настройка включена. Проблема в том, что когда настройка отключена, эти типы сетей вообще не обязательно появляются в списке. Мне кажется неправильным использовать сравнение строк специально для HSPA и UMTS для "connectionDisabled".

Как правильно решить эту проблему?

2 ответа

Решение

Для небольшого подмножества устройств (специально для LG Optimus 2X Speed, LG-P990) ответ выглядит так:

int enabled = Settings.Secure.getInt(getContentResolver(),
        "preferred_network_mode", -1);
Log.d("MYAPP", "2G only enabled: " + enabled);

Где параметр "использовать только сети 2G" указан как:

  • 0 указывает, что настройка отключена
  • 1 указывает, что настройка включена
  • -1 означает, что настройка не установлена ​​(некоторые устройства?)

Как я это обнаружил? Я собрал все пары ключ / значение из Settings.Secure используя следующее:

ContentResolver cr = getContentResolver();
Cursor cursor = cr.query(Settings.Secure.CONTENT_URI, null, null, null, null);
if (cursor.moveToFirst()) {
    while (!cursor.isAfterLast()) {
        Log.d("MYAPP", "cursor: "
                + cursor.getString(0) + ", "
                + cursor.getString(1) + ", "
                + cursor.getString(2));
        cursor.moveToNext();
    }
}

Я сравнил результаты между включением и отключением параметра и, конечно же, получил:

07-08 00: 15: 20.991: DEBUG / MYAPP (13813): курсор: 5154, предпочитаемый_сетевой_мод, 1

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

Хотя это соотносится с некоторой документацией для Settings.Secure, которую я нашел в Интернете, это значение не соблюдается всеми телефонами.

Если ваше устройство возвращается -1, возможно, перечисление пар ключ-значение покажет, какой параметр вам нужен. Пожалуйста, прокомментируйте, если вы столкнулись с этим!

Насколько я могу судить, не существует документированного способа получения значения для этого параметра. Но есть Use2GOnlyCheckBoxPreference класс, который можно использовать в качестве примера. Он использует внутренний Phone а также PhoneFactory классы для получения текущей стоимости prefer_2g установка.

Ты можешь использовать Phone а также PhoneFactory классы через отражение. Но, конечно, это недокументировано и на свой страх и риск. Вот соответствующий код из Use2GOnlyCheckBoxPreference:

import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;

public class Use2GOnlyCheckBoxPreference extends CheckBoxPreference {

    private Phone mPhone;
    private MyHandler mHandler;

    public Use2GOnlyCheckBoxPreference(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mPhone = PhoneFactory.getDefaultPhone();
        mHandler = new MyHandler();
        mPhone.getPreferredNetworkType(
                mHandler.obtainMessage(MyHandler.MESSAGE_GET_PREFERRED_NETWORK_TYPE));
    }

    private class MyHandler extends Handler {

        private static final int MESSAGE_GET_PREFERRED_NETWORK_TYPE = 0;

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MESSAGE_GET_PREFERRED_NETWORK_TYPE:
                    handleGetPreferredNetworkTypeResponse(msg);
                    break;
            }
        }

        private void handleGetPreferredNetworkTypeResponse(Message msg) {
            AsyncResult ar = (AsyncResult) msg.obj;

            if (ar.exception == null) {
                int type = ((int[])ar.result)[0];
                Log.i(LOG_TAG, "get preferred network type="+type);
                setChecked(type == Phone.NT_MODE_GSM_ONLY);
            } else {
                // Weird state, disable the setting
                Log.i(LOG_TAG, "get preferred network type, exception="+ar.exception);
                setEnabled(false);
            }
        }
    }   
}
Другие вопросы по тегам