我在哪里? – 得到国家

一个Android手机实际上确实知道它在哪里 – 但是有没有一种像国家代码一样检索国家的方法?

没有必要知道确切的GPS位置 – 国家是足够的

我首先想到的是使用时区,但实际上我需要更多的信息,因为如果位置是纽约或利马它会有所作为。

问题的背景:我有一个使用温度值的应用程序,我想设置默认单位为摄氏或华氏,取决于位置是美国还是外部

这将得到国家代码 :

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

也可以用getISO3Country()来代替getCountry()来获得国家的3个字母的ISO代码。 这将得到国名 :

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

这似乎比其他方法更容易,并依靠手机上的本地化设置,所以如果一个美国用户在国外,他们可能仍然希望华氏,这将工作:)

 /** * Get ISO 3166-1 alpha-2 country code for this device (or null if not available) * @param context Context reference to get the TelephonyManager instance from * @return country code or null */ public static String getUserCountry(Context context) { try { final TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); final String simCountry = tm.getSimCountryIso(); if (simCountry != null && simCountry.length() == 2) { // SIM country code is available return simCountry.toLowerCase(Locale.US); } else if (tm.getPhoneType() != TelephonyManager.PHONE_TYPE_CDMA) { // device is not 3G (would be unreliable) String networkCountry = tm.getNetworkCountryIso(); if (networkCountry != null && networkCountry.length() == 2) { // network country code is available return networkCountry.toLowerCase(Locale.US); } } } catch (Exception e) { } return null; } 

实际上,我发现使用TelephoneManager的getSimCountryIso()方法还有一种获得国家代码的方法:

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

由于它是SIM卡代码,所以在旅行到其他国家时也不应该改变。

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

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

示例json

 { "status": "success", "country": "United States", "countryCode": "US", "region": "CA", "regionName": "California", "city": "San Francisco", "zip": "94105", "lat": "37.7898", "lon": "-122.3942", "timezone": "America/Los_Angeles", "isp": "Wikimedia Foundation", "org": "Wikimedia Foundation", "as": "AS14907 Wikimedia US network", "query": "208.80.152.201" } 

注意 :因为这是第三方的解决scheme,所以只有在别人没有工作的情况下才能使用。

首先,获取LocationManager。 然后,调用LocationManager.getLastKnownPosition 。 然后创build一个GeoCoder并调用GeoCoder.getFromLocation 。 这是在一个单独的线程! 这会给你一个Address对象列表。 调用Address.getCountryName ,你明白了。

请记住,最后一个已知位置可能有点陈旧,所以如果用户刚刚越过边界,可能暂时不知道。

您可以使用getNetworkCountryIso()来获取手机当前所在的国家(尽pipe在CDMAnetworking中显然这是不可靠的)。

以下是基于LocationManager的完整解决scheme,以及TelephonyManager和networking提供商位置的后备scheme。 我使用了@Marco W.的回答部分的上面的答案(很好的答案本身!)。

注意:代码包含PreferencesManager,这是一个辅助类,用于保存和加载SharedPrefrences中的数据。 我用它来拯救国家到S“P,如果它是空的,我只能得到国家,对于我的产品,我并不是真的在乎所有的边缘情况(用户在国外旅行等等)。

 public static String getCountry(Context context) { String country = PreferencesManager.getInstance(context).getString(COUNTRY); if (country != null) { return country; } LocationManager locationManager = (LocationManager) PiplApp.getInstance().getSystemService(Context.LOCATION_SERVICE); if (locationManager != null) { Location location = locationManager .getLastKnownLocation(LocationManager.GPS_PROVIDER); if (location == null) { location = locationManager .getLastKnownLocation(LocationManager.NETWORK_PROVIDER); } if (location != null) { Geocoder gcd = new Geocoder(context, Locale.getDefault()); List<Address> addresses; try { addresses = gcd.getFromLocation(location.getLatitude(), location.getLongitude(), 1); if (addresses != null && !addresses.isEmpty()) { country = addresses.get(0).getCountryName(); if (country != null) { PreferencesManager.getInstance(context).putString(COUNTRY, country); return country; } } } catch (Exception e) { e.printStackTrace(); } } } country = getCountryBasedOnSimCardOrNetwork(context); if (country != null) { PreferencesManager.getInstance(context).putString(COUNTRY, country); return country; } return null; } /** * Get ISO 3166-1 alpha-2 country code for this device (or null if not available) * * @param context Context reference to get the TelephonyManager instance from * @return country code or null */ private static String getCountryBasedOnSimCardOrNetwork(Context context) { try { final TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); final String simCountry = tm.getSimCountryIso(); if (simCountry != null && simCountry.length() == 2) { // SIM country code is available return simCountry.toLowerCase(Locale.US); } else if (tm.getPhoneType() != TelephonyManager.PHONE_TYPE_CDMA) { // device is not 3G (would be unreliable) String networkCountry = tm.getNetworkCountryIso(); if (networkCountry != null && networkCountry.length() == 2) { // network country code is available return networkCountry.toLowerCase(Locale.US); } } } catch (Exception e) { } return null; } 

使用GPS经纬度,我们可以得到国家代码。

如果我们使用电话,如果我们不使用SIM卡,并且在语言环境中,基于语言,它会以错误的方式显示国家代码。

MainActivity.java:

  GPSTracker gpsTrack; public static double latitude = 0; public static double longitude = 0; gpsTrack = new GPSTracker(TabHomeActivity.this); if (gpsTrack.canGetLocation()) { latitude = gpsParty.getLatitude(); longitude = gpsParty.getLongitude(); Log.e("GPSLat", "" + latitude); Log.e("GPSLong", "" + longitude); } else { gpsTrack.showSettingsAlert(); Log.e("ShowAlert", "ShowAlert"); } countryCode = getAddress(TabHomeActivity.this, latitude, longitude); Log.e("countryCode", ""+countryCode); public String getAddress(Context ctx, double latitude, double longitude) { String region_code = null; try { Geocoder geocoder = new Geocoder(ctx, Locale.getDefault()); List<Address> addresses = geocoder.getFromLocation(latitude, longitude, 1); if (addresses.size() > 0) { Address address = addresses.get(0); region_code = address.getCountryCode(); } } catch (IOException e) { Log.e("tag", e.getMessage()); } return region_code; } 

GPSTracker.java:

 import android.app.AlertDialog; import android.app.Service; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; import android.os.IBinder; import android.provider.Settings; import android.util.Log; public class GPSTracker extends Service implements LocationListener { private final Context mContext; // flag for GPS status boolean isGPSEnabled = false; // flag for network status boolean isNetworkEnabled = false; // flag for GPS status boolean canGetLocation = false; Location location; // location double latitude; // latitude double longitude; // longitude // The minimum distance to change Updates in meters private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters // The minimum time between updates in milliseconds private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1; // 1 minute // Declaring a Location Manager protected LocationManager locationManager; public GPSTracker(Context context) { this.mContext = context; getLocation(); } public Location getLocation() { try { locationManager = (LocationManager) mContext .getSystemService(LOCATION_SERVICE); // getting GPS status isGPSEnabled = locationManager .isProviderEnabled(LocationManager.GPS_PROVIDER); // getting network status isNetworkEnabled = locationManager .isProviderEnabled(LocationManager.NETWORK_PROVIDER); if (!isGPSEnabled && !isNetworkEnabled) { // no network provider is enabled } else { this.canGetLocation = true; // First get location from Network Provider if (isNetworkEnabled) { locationManager.requestLocationUpdates( LocationManager.NETWORK_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this); Log.d("Network", "Network"); if (locationManager != null) { location = locationManager .getLastKnownLocation(LocationManager.NETWORK_PROVIDER); if (location != null) { latitude = location.getLatitude(); longitude = location.getLongitude(); } } } // if GPS Enabled get lat/long using GPS Services if (isGPSEnabled) { if (location == null) { locationManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this); Log.d("GPS Enabled", "GPS Enabled"); if (locationManager != null) { location = locationManager .getLastKnownLocation(LocationManager.GPS_PROVIDER); if (location != null) { latitude = location.getLatitude(); longitude = location.getLongitude(); } } } } } } catch (Exception e) { e.printStackTrace(); } return location; } /** * Stop using GPS listener * Calling this function will stop using GPS in your app * */ public void stopUsingGPS(){ if(locationManager != null){ locationManager.removeUpdates(GPSTracker.this); } } /** * Function to get latitude * */ public double getLatitude(){ if(location != null){ latitude = location.getLatitude(); } // return latitude return latitude; } /** * Function to get longitude * */ public double getLongitude(){ if(location != null){ longitude = location.getLongitude(); } // return longitude return longitude; } /** * Function to check GPS/wifi enabled * @return boolean * */ public boolean canGetLocation() { return this.canGetLocation; } public void showSettingsAlert() { final AlertDialog.Builder builder = new AlertDialog.Builder(mContext); builder.setMessage("Your GPS seems to be disabled, do you want to enable it?") .setCancelable(false) .setPositiveButton("Yes", new DialogInterface.OnClickListener() { public void onClick(@SuppressWarnings("unused") final DialogInterface dialog, @SuppressWarnings("unused") final int id) { mContext.startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS)); } }) .setNegativeButton("No", new DialogInterface.OnClickListener() { public void onClick(final DialogInterface dialog, @SuppressWarnings("unused") final int id) { dialog.cancel(); } }); final AlertDialog alert = builder.create(); alert.show(); } @Override public void onLocationChanged(Location location) { } @Override public void onProviderDisabled(String provider) { } @Override public void onProviderEnabled(String provider) { } @Override public void onStatusChanged(String provider, int status, Bundle extras) { } @Override public IBinder onBind(Intent arg0) { return null; } } 

日志:

E / countryCode: IN

编辑:使用熔合位置提供程序获取经纬度更新,以获得更好的结果。

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

已弃用。 用这个代替:

 Locale locale; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { locale = context.getResources().getConfiguration().getLocales().get(0); } else { locale = context.getResources().getConfiguration().locale; } 

我使用了GEOIP db并创build了一个函数。 你可以直接使用这个链接http://jamhubsoftware.com/geoip/getcountry.php

 {"country":["India"],"isoCode":["IN"],"names":[{"de":"Indien","en":"India","es":"India","fr":"Inde","ja":"\u30a4\u30f3\u30c9","pt-BR":"\u00cdndia","ru":"\u0418\u043d\u0434\u0438\u044f","zh-CN":"\u5370\u5ea6"}]} 

你可以从https://dev.maxmind.com/geoip/geoip2/geolite2/下载autoload.php和;.mmdb文件

 ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL); $ip_address = $_SERVER['REMOTE_ADDR']; //$ip_address = '3.255.255.255'; require_once 'vendor/autoload.php'; use GeoIp2\Database\Reader; // This creates the Reader object, which should be reused across // lookups. $reader = new Reader('/var/www/html/geoip/GeoLite2-City.mmdb'); // Replace "city" with the appropriate method for your database, eg, // "country". $record = $reader->city($ip_address); //print($record->country->isoCode . "\n"); // 'US' //print($record->country->name . "\n"); // 'United States' $rows['country'][] = $record->country->name; $rows['isoCode'][] = $record->country->isoCode; $rows['names'][] = $record->country->names; print json_encode($rows); //print($record->country->names['zh-CN'] . "\n"); // '美国' // //print($record->mostSpecificSubdivision->name . "\n"); // 'Minnesota' //print($record->mostSpecificSubdivision->isoCode . "\n"); // 'MN' // //print($record->city->name . "\n"); // 'Minneapolis' // //print($record->postal->code . "\n"); // '55455' // //print($record->location->latitude . "\n"); // 44.9733 //print($record->location->longitude . "\n"); // -93.2323 ?>