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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11293642/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 06:47:32  来源:igfitidea点击:

how can i get my android device country code without using GPS?

androidlocale

提问by Vikas Goyal

An android mobile actually does know quite well where it is - but is there a way of retrieving the country by something like a country code or country name?

安卓手机实际上很清楚它在哪里——但是有没有办法通过国家代码或国家名称之类的东西来检索国家?

No need of knowing the exact GPS position - the country code or name is sufficient, and i am using the code for this:

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

 String locale = context.getResources().getConfiguration().locale.getCountry(Locale.getDefault());      
 System.out.println("country = "+locale);

but it gives me code "US"
but my device kept in india; is there any way to find device current country code without using GPS or Network Provider. because i am using Tablet. Thanks in Advance.

但它给了我代码“美国”,
但我的设备保存在印度;有没有办法在不使用 GPS 或网络提供商的情况下找到设备当前的国家/地区代码。因为我正在使用平板电脑。提前致谢。

回答by Rawkode

You shouldn't be passing anything in to getCountry(), remove Locale.getDefault()

你不应该将任何东西传递给getCountry(), removeLocale.getDefault()

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

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

回答by Kishath

You can simply use this code,

您可以简单地使用此代码,

TelephonyManager tm = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE);
String countryCodeValue = tm.getNetworkCountryIso();

This will return 'US' if your current connected network is United states. This works without SIM card even. Hope this will solve your problem.

如果您当前连接的网络是美国,这将返回“美国”。这甚至可以在没有 SIM 卡的情况下工作。希望这能解决您的问题。

回答by shine_joseph

Use this link http://ip-api.com/json,this will provide all the information as json. From this json you can get the country easily. This site works using your current IP,it automatically detects the IP and sendback details.

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

Docs http://ip-api.com/docs/api:jsonHope it helps.

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

This is what I got.

这就是我得到的。

{
"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": ""
}

N.B. - As this is a 3rd party api, do not use as a primary solution. And also not sure whether its free or not.

注意 - 由于这是第 3 方 api,请勿用作主要解决方案。而且也不确定它是否免费。

回答by Egemen Hamut?u

The checked answer has deprecated code. You need to implement this:

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

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();
}

回答by radu_paun

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.

这是一个完整的例子。尝试从 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 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.

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

References hereand here

参考这里这里

回答by MarGin

For some devices, if the default language is set different (an indian can set English (US)) then

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

context.getResources().getConfiguration().locale.getDisplayCountry();

will give wrong value .So this method is non reliable

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

Also, getNetworkCountryIso() method of TelephonyManager will not work on devices which don't have SIM card (WIFI tablets).

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

If a device doesn't have SIM then we can use Time Zone to get the country. For countries like India, this method will work

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

sample code used to check the country is India or not (Time zone id : asia/calcutta)

用于检查国家是否为印度的示例代码(时区 ID:asia/calcutta)

private void checkCountry() {


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

    int simState = telMgr.getSimState();

    switch (simState) {
        //if sim is not available then country is find out using 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 sim is available then telephony manager network country info 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;

    }
}

回答by Killer

I have created a utility function (tested once on a device where I was getting incorrect country code based on locale). Hope that help. Reference: https://github.com/hbb20/CountryCodePickerProject/blob/master/ccp/src/main/java/com/hbb20/CountryCodePicker.java#L1965

我创建了一个实用程序函数(在我根据语言环境获得不正确的国家/地区代码的设备上测试过一次)。希望有所帮助。 参考https: //github.com/hbb20/CountryCodePickerProject/blob/master/ccp/src/main/java/com/hbb20/CountryCodePicker.java#L1965

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.simCountryIso}")
            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, "detectNetworkCountry: $localeCountryISO")
            return localeCountryISO
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return null
    }

回答by pavel

No need to call any api. You can get country code from your device where it located just use this function

无需调用任何api。您可以从设备所在的位置获取国家/地区代码,只需使用此功能

 fun getUserCountry(context: Context): String? {
    try {
        val tm = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
        val simCountry = tm.simCountryIso
        if (simCountry != null && simCountry.length == 2) { // SIM country code is available
            return simCountry.toLowerCase(Locale.US)
        } else if (tm.phoneType != TelephonyManager.PHONE_TYPE_CDMA) { // device is not 3G (would be unreliable)
            val networkCountry = tm.networkCountryIso
            if (networkCountry != null && networkCountry.length == 2) { // network country code is available
                return networkCountry.toLowerCase(Locale.US)
            }
        }
    } catch (e: Exception) {
    }
    return null
}

回答by Blue_Alien

if you wish to get the country code without asking for any permission, you can choose a tricky way.

如果你想在不征得任何许可的情况下获得国家代码,你可以选择一个棘手的方式。

the method simply uses API to get the country code, and it is not any third party libraries to depend on, we can create one for us.

该方法只是简单地使用API​​获取国家代码,不依赖任何第三方库,我们可以自己创建一个。

here i have used Google Cloud Functionsto write API and it is so effortless.

在这里,我使用了Google Cloud Functions来编写 API,它非常轻松。

Step 1: Create a Google Cloud Account, and setup billing (there is enough free tier)

第 1 步:创建一个 Google Cloud 帐户,并设置计费(有足够的免费层)

Step 2: Create Cloud Function to get Geo Location

第 2 步:创建云函数以获取地理位置

copy this basic function to the code editor of index.js

将这个基本函数复制到 index.js 的代码编辑器中

const cors = require('cors')

function _geolocation(req, res) {
  const data = {
    country_code: req.headers["x-appengine-country"],
    region: req.headers["x-appengine-region"],
    city: req.headers["x-appengine-city"],
    cityLatLong: req.headers["x-appengine-citylatlong"],
    userIP: req.headers["x-appengine-user-ip"]
  }

  res.json(data)
};

exports.geolocation = (req, res) => {
  const corsHandler = cors({ origin: true })

  return corsHandler(req, res, function() {
    return _geolocation(req, res);
  });
};

also need to copy the package.json definition

还需要复制 package.json 定义

{
  "name": "gfc-geolocation",
  "version": "0.0.1",
  "dependencies": {
    "cors": "^2.8.4"
  }
}

Step 3: finish, and get the URL similar to : "https://us-central1-geolocation-mods-sdde.cloudfunctions.net/geolocation"

第三步:完成,得到类似如下的URL: "https://us-central1-geolocation-mods-sdde.cloudfunctions.net/geolocation"

Step 4: parse the JSON response and get the country code

第 4 步:解析 JSON 响应并获取国家/地区代码

the response will look like:

响应将如下所示:

{
   "country":"IN",
   "region":"kl",
   "city":"kochi",
   "cityLatLong":"9.9312,76.2673",
   "userIP":"xx.xx.xx.xx"
}

thanks and credits to the medium article : Free IP-based GeoLocation with Google Cloud Functions

感谢并感谢媒体文章:使用 Google Cloud Functions 的免费基于 IP 的地理定位