How to get Country (or its ISO code)?

2019-01-13 07:38发布

问题:

What is the best way to get country code? As of now I know two ways one is to get by TelephonyManager and another by Locale which is the other best & unique way to find country code in android.

回答1:

Try this,

TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
      String countryCode = tm.getSimCountryIso();


回答2:

There are always huge discussions about this, and I never understand why developers and companies go for the complex way. The language selected by the user, means the language he/she wants to see always in his/her phone. They don't intend to have apps in a different language than others or the system.

The choice is very straight forward: Use Locale (to get the language the user selected as preferred), or make your best to piss them off showing them information in a language they already said they don't want to see things in.

To get the country code use:

Locale.getDefault().getCountry();


回答3:

            TelephonyManager tm = (TelephonyManager)getSystemService(getApplicationContext().TELEPHONY_SERVICE);
          String countryCode = tm.getNetworkCountryIso();

It is better than getSimCountryIsobecause getSimCountryIso depends on the operator to burn the country iso on the SIM and it also supports CDMA networks.



回答4:

I solved it by IP Address. You can get IP Address of your phone. If you are using wifi then it will IP address of wifi hotspot or IP of your Mobile Service Provide server so from that IP you can send to web service or something to track country of that IP Address there are some sources(database) available if internet which provides country of IP here is the example http://whatismyipaddress.com/ip-lookup.



回答5:

I think ip is the best way because it will give you the country where the phone is at the momment,

If you do it by

    Locale.getDefault().getCountry();,

you got the country where the user select the country so you can have selected England, and you can be in Spain and maybe you need to know where is him at the momment

Example: imagine that your app can buy something ONLY in england, the user is from Spain but he is on holidays on England and he want to buy your product ... if you use

    Locale.getDefault().getCountry(); 

that user wont be able to buy your product,so the ip is the best way i think



回答6:

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 location of an android device, including source code. Next, when you have location, it's easy to get country for it - use can use online web-service or offline database



回答7:

You can use this code to get ISO2: Locale.getDefault().getCountry()

And this to get ISO3: Locale.getDefault().getISO3Country()

Hope this helps



回答8:

I know it's a very old question but I think this will help some of devs:

It's very hard to find the country without GPS and Google Services (China). TelephonyManager won't work if there is no SIM in your phone.

And Locale won't work if a user in China set his language as English (the country you will be getting will be US or UK).

If your app requires internet connection then there is an option. You could use this API called ip-api. Please go through there documentation first if you are planing to use this

There are other APIs like this freegeoip api



回答9:

Here is a complete example. Try to get country code from TelephonyManager (from SIM or CDMA devices), and if not available try to get it from local configuration.

private static String getDeviceCountryCode(Context context) {
    String countryCode;

    // try to get country code from 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 SIM) query getNetworkCountryIso()
            countryCode = tm.getNetworkCountryIso();
        }

        if (countryCode != null && countryCode.length() == 2)
            return countryCode.toLowerCase();
    }

    // if network country not available (tablets maybe), get country code from 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 3 chars (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 here and here