如何在不使用GPS的情况下获取我的Android设备国家代码?

Vik*_*yal 51 android locale

Android移动设备实际上确实知道它在哪里 - 但有没有办法通过国家代码或国家/地区名称来检索国家/地区?

无需知道确切的GPS位置 - 国家代码或名称就足够了,我正在使用以下代码:

 String locale = context.getResources().getConfiguration().locale.getCountry(Locale.getDefault());      
 System.out.println("country = "+locale);
Run Code Online (Sandbox Code Playgroud)

但它给了我"美国"代码,
但我的设备保存在印度; 有没有办法找到设备当前国家代码而不使用GPS或网络提供商.因为我正在使用平板电脑 提前致谢.

Raw*_*ode 76

你不应该传递任何东西getCountry(),删除Locale.getDefault()

String locale = context.getResources().getConfiguration().locale.getCountry();

  • 这将返回用户配置的Locale的国家/地区.如果用户为印度配置设备然后将其带到德国的飞机上,您仍然可以获得印度的国家代码.我想我会澄清一下. (71认同)
  • 这已在API级别24中弃用. (6认同)
  • 我住在比利时,我的设备是英语/美国,我不确定这个代码会给出这个国家 ;-) (3认同)
  • 有没有可能,无论那个调用返回 "" 或 null 多么渺茫?不是实际的国家代码? (2认同)

Kis*_*ath 63

你可以简单地使用这段代码,

TelephonyManager tm = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE);
String countryCodeValue = tm.getNetworkCountryIso();
Run Code Online (Sandbox Code Playgroud)

如果您当前连接的网络是美国,这将返回"美国".这甚至没有SIM卡.希望这能解决你的问题.

  • 没有SIM卡在Nexus 5中无法使用! (6认同)
  • 这不需要任何权限,但它需要 FEATURE_TELEPHONY_RADIO_ACCESS 功能,这意味着(正如 @AlbertoAnderickJr 所指出的)设备必须具有 SIM 卡才能实现此功能。因此,您可以使用 PackageManager.hasSystemFeature 检查设备是否支持此功能,如下所示:https://developer.android.com/reference/android/telephony/TelephonyManager#getNetworkCountryIso() (4认同)
  • 它不适用于没有仅适用于Wifi的SIM卡或平板电脑的设备 (3认同)
  • 所有TelephonyManager所需的权限https://developer.android.com/reference/android/telephony/TelephonyManager.html (2认同)
  • @Ben.Slama.Jihed 不是全部。根据您提到的文档:“请注意,对某些电话信息的访问是受权限保护的。” 我认为“getNetworkCountryIso()”不需要额外的权限。 (2认同)

shi*_*eph 45

使用此链接http://ip-api.com/json ,这将提供所有信息为json.从这个json你可以很容易地到达这个国家.此站点使用您当前的IP工作,它会自动检测IP和发送回复的详细信息.

文档http://ip-api.com/docs/api:json 希望它有所帮助.

这就是我得到的.

{
"as": "AS55410 C48 Okhla Industrial Estate, New Delhi-110020",
"city": "Kochi",
"country": "India",
"countryCode": "IN",
"isp": "Vodafone India",
"lat": 9.9667,
"lon": 76.2333,
"org": "Vodafone India",
"query": "123.63.81.162",
"region": "KL",
"regionName": "Kerala",
"status": "success",
"timezone": "Asia/Kolkata",
"zip": ""
}
Run Code Online (Sandbox Code Playgroud)

注意 - 由于这是第三方API,请不要将其用作主要解决方案.而且还不确定它是否免费.

  • 使用 VPN 时这也会提供正确的国家/地区吗? (3认同)
  • 啊哈!我躺在俄罗斯莫斯科的沙发上,它给了我 {"as":"AS15169 Google LLC","city":"Ashburn","country":"United States","countryCode":" US","isp":"Google LLC","lat":39.0438,"lon":-77.4874,"org":"Google LLC","query":"66.102.9.142","re​​gion":"VA ","re​​gionName":"弗吉尼亚州","状态":"成功","时区":"美国/纽约","zip":"20149"} (2认同)

Kil*_*ler 10

我创建了一个实用程序函数(在我根据语言环境获得不正确的国家/地区代码的设备上测试过一次)。

参考CountryCodePicker.java

fun getDetectedCountry(context: Context, defaultCountryIsoCode: String): String {

    detectSIMCountry(context)?.let {
        return it
    }

    detectNetworkCountry(context)?.let {
        return it
    }

    detectLocaleCountry(context)?.let {
        return it
    }

    return defaultCountryIsoCode
}

private fun detectSIMCountry(context: Context): String? {
    try {
        val telephonyManager = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
        Log.d(TAG, "detectSIMCountry: ${telephonyManager.simCountryIso}")
        return telephonyManager.simCountryIso
    }
    catch (e: Exception) {
        e.printStackTrace()
    }
    return null
}

private fun detectNetworkCountry(context: Context): String? {
    try {
        val telephonyManager = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
        Log.d(TAG, "detectNetworkCountry: ${telephonyManager.networkCountryIso}")
        return telephonyManager.networkCountryIso
    }
    catch (e: Exception) {
        e.printStackTrace()
    }
    return null
}

private fun detectLocaleCountry(context: Context): String? {
    try {
        val localeCountryISO = context.getResources().getConfiguration().locale.getCountry()
        Log.d(TAG, "detectLocaleCountry: $localeCountryISO")
        return localeCountryISO
    }
    catch (e: Exception) {
        e.printStackTrace()
    }
    return null
}
Run Code Online (Sandbox Code Playgroud)


rad*_*aun 9

这是一个完整的例子。它尝试从 TelephonyManager(从 SIM 或 CDMA 设备)获取国家代码,如果不可用,则尝试从本地配置获取它。

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 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;
}
Run Code Online (Sandbox Code Playgroud)

另一个想法是尝试像这个答案中的 API 请求。

参考资料在这里这里


Ege*_*tçu 8

已检查的答案已弃用代码.你需要实现这个:

String locale;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    locale = context.getResources().getConfiguration().getLocales().get(0).getCountry();
} else {
    locale = context.getResources().getConfiguration().locale.getCountry();
}
Run Code Online (Sandbox Code Playgroud)

  • 这总是返回美国 (3认同)
  • Jip,我住在南非,我所有的设备都默认为美国 (2认同)

Mar*_*Gin 7

对于某些设备,如果默认语言设置不同(印度人可以设置英语(美国)),则

context.getResources().getConfiguration().locale.getDisplayCountry();
Run Code Online (Sandbox Code Playgroud)

会给出错误的值。所以这种方法是不可靠的。

此外,TelephonyManager 的 getNetworkCountryIso() 方法不适用于没有 SIM 卡的设备(Wi-Fi 平板电脑)。

如果设备没有 SIM 卡,那么我们可以使用时区来获取国家/地区。对于像印度这样的国家,这种方法会奏效。

用于检查国家是否为印度的示例代码。

在常量文件中使用以下值

(Constants.INDIA_TIME_ZONE_ID: "asia/calcutta", Constants.NETWORK_INDIA_CODE :"in")

在您的活动中,添加以下代码:

private void checkCountry() {

    TelephonyManager telMgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
    if (telMgr == null)
        return;

    int simState = telMgr.getSimState();

    switch (simState) {

        // If a SIM card is not available then the
        // country is found using the timezone ID
        case TelephonyManager.SIM_STATE_ABSENT:
            TimeZone tz = TimeZone.getDefault();
            String timeZoneId = tz.getID();
            if (timeZoneId.equalsIgnoreCase(Constants.INDIA_TIME_ZONE_ID)) {
               // Do something
            }
            else {
               // Do something
            }
            break;

        // If a SIM card is available then the telephony
        // manager network country information is used
        case TelephonyManager.SIM_STATE_READY:

            if (telMgr != null) {
                String countryCodeValue = tm.getNetworkCountryIso();

                // Check if the network country code is "in"
                if (countryCodeValue.equalsIgnoreCase(Constants.NETWORK_INDIA_CODE)) {
                   // Do something
                }
                else {
                   // Do something
                }
            }
            break;
    }
}
Run Code Online (Sandbox Code Playgroud)