Detecting "use only 2G networks" setting
Is there a way of returning the value of Android's mobile network setting for "use only 2G networks"?
The app being developed measures the internet speed at a certain location, but in order for this to be relevant, it must know if the user is deliberately restricting mobile internet to 2G.
I've taken a look at ConnectivityManager, but it only provides information about the background data setting or all networks. Iterating through them reveals that despite the setting being enabled, HSPA and UMTS return true
for isAvailable()
:
for (NetworkInfo netInfo : cm.getAllNetworkInfo()) {
Log.i(TAG, netInfo.getSubtypeName() + ": " + netInfo.isAvailable());
}
The only hint I've found amidst all this is that netInfo.getReason()
returns "connectionDisabled" on HSPA and UMTS when the setting is enabled. The t开发者_高级运维rouble is, when the setting is disabled, those network types don't necessarily appear in the list at all. It doesn't seem right to me to use a string comparison specifically on HSPA and UMTS for "connectionDisabled".
What's the right way of tackling this?
For a small subset of devices (specifically for the LG Optimus 2X Speed, LG-P990), an answer seems to be:
int enabled = Settings.Secure.getInt(getContentResolver(),
"preferred_network_mode", -1);
Log.d("MYAPP", "2G only enabled: " + enabled);
Where the "use only 2G networks" setting is specified as:
0
indicates the setting is disabled1
indicates the setting is enabled-1
indicates the setting is not set (some devices?)
How I discovered this? I gathered all the key/value pairs from Settings.Secure
using the following:
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();
}
}
I compared results between enabling and disabling the setting, and sure enough I got:
07-08 00:15:20.991: DEBUG/MYAPP(13813): cursor: 5154, preferred_network_mode, 1
Do NOT use the index column (5154 in the example above), as I've noticed it changes between toggling the setting.
Although this correlates with some documentation for Settings.Secure I found online, this value isn't respected by all phones.
If your device returns -1
, perhaps listing the key value pairs will reveal which setting you need. Please comment if you encounter it!
As far as I can tell, there is no documented way of getting value for that setting. But there is a Use2GOnlyCheckBoxPreference
class that can be used as an example. It uses internal Phone
and PhoneFactory
classes to obtain the current value of prefer_2g
setting.
You can use Phone
and PhoneFactory
classes via reflection. But of cause this is undocumented and is on your own risk. Here is relevant code from 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);
}
}
}
}
精彩评论