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

时间:2012-07-02 12:24:22

标签: android locale

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

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

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

但它给了我代码“US”
但我的设备留在了印度; 有没有办法找到设备当前国家代码而不使用GPS或网络提供商。 因为我正在使用平板电脑 在此先感谢。

11 个答案:

答案 0 :(得分:72)

你不应该将任何内容传递给getCountry(),删除Locale.getDefault()

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

答案 1 :(得分:60)

您只需使用此代码

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

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

答案 2 :(得分:42)

使用此链接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": ""
}

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

答案 3 :(得分: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();
}

答案 4 :(得分:4)

如果您希望在不征得任何许可的情况下获取国家/地区代码,则可以选择一种棘手的方法。

该方法仅使用API​​来获取国家/地区代码,并且没有任何依赖的第三方库。我们可以为我们创建一个。

这里我用Google Cloud Functions编写了一个API,它很轻松。

第1步:创建一个Google Cloud帐户,然后设置结算(免费套餐就足够了)

第2步:创建云功能以获取地理位置

将此基本功能复制到 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);
  });
};

我们还需要复制 package.json 定义:

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

第3步:完成操作,并获得类似于"https://us-central1-geolocation-mods-sdde.cloudfunctions.net/geolocation"

的URL

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

响应如下:

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

感谢和感谢,敬请访问Medium文章:Free IP-based Geolocation with Google Cloud Functions

答案 5 :(得分:2)

我创建了一个实用程序功能(在我根据语言环境获取不正确的国家代码的设备上进行了一次测试)。希望对您有所帮助。 参考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
    }

答案 6 :(得分:2)

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

SELECT c.balance + 
(
    SELECT SUM(CASE WHEN movementType = 'payment' THEN - import
                            WHEN movementType = 'refund' THEN  import
                          ELSE 0 END)
    FROM balance_Movements bb
    WHERE bb.id <= b.id and b.clientid = bb.clientid
)  Total
FROM client c 
JOIN balance_Movements b on c.id = b.clientid

将给出错误的值。因此此方法不可靠

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

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

用于检查国家/地区为印度的示例代码 (时区ID:亚洲/ Calcutta)

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

答案 7 :(得分:1)

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

另一个想法是尝试使用answer中的API请求。

引用herehere

答案 8 :(得分:0)

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

 render() {
  return <>
   {this.state.items.map(el => (
      <div
        key={el.id}
        onClick={() => this.handleToggle(el.id)}
        className={el.expanded ? "faq__columns--item--active faq__columns--item" : "faq__columns--item"}
      >
        <div className="faq__content">
          <p className="mb-0">{el.answer}</p>
          {el.email ? <div>show link</div> : <div>no link</div>}
        </div>
      </div>
    ));}
   </>
  }

答案 9 :(得分:0)

<块引用>

获取国家代码

<uses-permission android:name="android.permission.INTERNET" />

public String makeServiceCall() {
    String response = null;
    String reqUrl = "https://ipinfo.io/country";
    try {
        URL url = new URL(reqUrl);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        // read the response
        InputStream in = new BufferedInputStream(conn.getInputStream());
        response = convertStreamToString(in);
    } catch (MalformedURLException e) {
        Log.e(TAG, "MalformedURLException: " + e.getMessage());
    } catch (ProtocolException e) {
        Log.e(TAG, "ProtocolException: " + e.getMessage());
    } catch (IOException e) {
        Log.e(TAG, "IOException: " + e.getMessage());
    } catch (Exception e) {
        Log.e(TAG, "Exception: " + e.getMessage());
    }
    return response;
}

答案 10 :(得分:-3)

不确定是否仍在搜索解决方案,但这是我的:

        private void getCountryCode(final Location location) {
    Helper.log(TAG, "getCountryCode");

    AsyncTask<Void, Void, String> countryCodeTask = new AsyncTask<Void, Void, String>() {

        final float latitude = (float) location.getLatitude();
        final float longitude = (float) location.getLongitude();
        // Helper.log(TAG, "latitude: " +latitude);
        List<Address> addresses = null;
        Geocoder gcd = new Geocoder(mContext);
        String code = null;

        @Override
        protected String doInBackground(Void... params) {
            try {
                addresses = gcd.getFromLocation(latitude, longitude, 1);
                code = addresses.get(0).getCountryCode();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return code;
        }

        @Override
        protected void onPostExecute(String code) {
            Helper.log(TAG, "onPostExecute");
            mCountryCodeListener.returnCountryCode(code);
        }

    };
    if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) {
        countryCodeTask.execute();
    } else {
        countryCodeTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
    }
}