What is the best way to get the country code?
As of now, I know two ways. One is to get by TelephonyManager and another by Locale. Which is another best and unique wa
There is an excellent article by Reto Meier: http://android-developers.blogspot.com/2011/06/deep-dive-into-location.html
It describes different techniques to get the location of an Android device, including source code.
Next, when you have the location, it's easy to get the country for it - you can use an online web-service or offline database.
Try this:
TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
String countryCode = tm.getSimCountryIso();
Here is a complete example. Try to get country code from TelephonyManager (from a SIM card or CDMA devices), and if not available, try to get it from the local configuration.
private static String getDeviceCountryCode(Context context) {
String countryCode;
// Try to get the country code from the TelephonyManager service
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
if(tm != null) {
// Query first getSimCountryIso()
countryCode = tm.getSimCountryIso();
if (countryCode != null && countryCode.length() == 2)
return countryCode.toLowerCase();
if (tm.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
// Special case for CDMA devices
countryCode = getCDMACountryIso();
} else {
// For 3G devices (with a SIM card), query getNetworkCountryIso()
countryCode = tm.getNetworkCountryIso();
}
if (countryCode != null && countryCode.length() == 2)
return countryCode.toLowerCase();
}
// If the network country is not available (tablets maybe), get the country code from the Locale class
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
countryCode = context.getResources().getConfiguration().getLocales().get(0).getCountry();
} else {
countryCode = context.getResources().getConfiguration().locale.getCountry();
}
if (countryCode != null && countryCode.length() == 2)
return countryCode.toLowerCase();
// General fallback to "us"
return "us";
}
@SuppressLint("PrivateApi")
private static String getCDMACountryIso() {
try {
// Try to get country code from SystemProperties private class
Class<?> systemProperties = Class.forName("android.os.SystemProperties");
Method get = systemProperties.getMethod("get", String.class);
// Get homeOperator that contain MCC + MNC
String homeOperator = ((String) get.invoke(systemProperties,
"ro.cdma.home.operator.numeric"));
// First three characters (MCC) from homeOperator represents the country code
int mcc = Integer.parseInt(homeOperator.substring(0, 3));
// Mapping just countries that actually use CDMA networks
switch (mcc) {
case 330: return "PR";
case 310: return "US";
case 311: return "US";
case 312: return "US";
case 316: return "US";
case 283: return "AM";
case 460: return "CN";
case 455: return "MO";
case 414: return "MM";
case 619: return "SL";
case 450: return "KR";
case 634: return "SD";
case 434: return "UZ";
case 232: return "AT";
case 204: return "NL";
case 262: return "DE";
case 247: return "LV";
case 255: return "UA";
}
}
catch (ClassNotFoundException ignored) {
}
catch (NoSuchMethodException ignored) {
}
catch (IllegalAccessException ignored) {
}
catch (InvocationTargetException ignored) {
}
catch (NullPointerException ignored) {
}
return null;
}
Also another idea is to try an API request like in this answer, or to use fine location.
References are here and here.