¿Dónde estoy? – Obtener país

Un móvil con Android realmente sabe bastante bien dónde está, pero ¿hay alguna forma de recuperar el país por medio de un código de país?

No es necesario conocer la posición exacta del GPS: el país es suficiente

Primero pensé en usar la zona horaria, pero en realidad necesito más información que eso, ya que hace una diferencia si la ubicación es Nueva York o Lima.

El trasfondo de la pregunta: tengo una aplicación que usa valores de temperatura, y me gustaría establecer la unidad predeterminada en Celsius o Fahrenheit, dependiendo de si la ubicación es en EE. UU. O fuera

Esto obtendrá el código de país :

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

también puede reemplazar getCountry () con getISO3Country () para obtener un código ISO de 3 letras para el país. Esto obtendrá el nombre del país :

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

Esto parece más fácil que los otros métodos y depende de la configuración de localización en el teléfono, por lo que si un usuario de EE. UU. Está en el extranjero, probablemente todavía quieran Fahrenheit y esto funcionará 🙂

 /** * 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; } 

De hecho, descubrí que hay incluso una forma más de obtener un código de país, utilizando el método getSimCountryIso () de TelephoneManager :

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

Como es el código SIM, tampoco debería cambiar cuando se viaja a otros países.

Use este enlace http://ip-api.com/json , esto proporcionará toda la información como json. Desde este momento, puedes obtener el país fácilmente. Este sitio funciona usando su IP actual, detecta automáticamente los detalles de IP y de envío.

Docs http://ip-api.com/docs/api:json Espero que ayude.

Ejemplo 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" } 

nota : Como esta es una solución de terceros, solo úsela si otros no funcionó.

Primero, obtenga el LocationManager. Luego, llama a LocationManager.getLastKnownPosition . Luego crea un GeoCoder y llama a GeoCoder.getFromLocation . ¡Haz esto en un hilo separado! Esto le dará una lista de objetos de Address . Llamar a Address.getCountryName y lo tienes.

Tenga en cuenta que la última posición conocida puede ser un poco obsoleta, por lo que si el usuario acaba de cruzar el borde, es posible que no lo sepa por un tiempo.

Puede usar getNetworkCountryIso() de TelephonyManager para obtener el país en el que se encuentra actualmente el teléfono (aunque aparentemente esto no es confiable en las redes CDMA).

Aquí hay una solución completa basada en el LocationManager y, como contrapartidas, el TelephonyManager y las ubicaciones del proveedor de red. Utilicé la respuesta anterior de @Marco W. para la parte alternativa (¡gran respuesta como ella misma!).

Nota: el código contiene PreferencesManager, esta es una clase auxiliar que guarda y carga datos desde SharedPrefrences. Lo estoy usando para guardar el país en S “P, solo obtengo el país si está vacío. Para mi producto, realmente no me preocupan todos los casos extremos (el usuario viaja al exterior, etc.).

 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); } else { Geocoder gcd = new Geocoder(context, Locale.getDefault()); List
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; }

Usando GPS con latitud y longitud, podemos obtener el código de país.

Si utilizamos la telefonía, no funcionará si no usamos la tarjeta SIM y en la configuración regional, según el idioma, muestra el código de país de manera incorrecta.

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

Iniciar sesión:

E / countryCode: IN

Editar: use Fused Location Provider para obtener la actualización de latitud y longitud para obtener mejores resultados.

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

Es obsoleto. Use esto en su lugar:

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

Utilicé GEOIP DB y creé una función. Puedes consumir este enlace directamente 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"}]} 

puede descargar archivos autoload.php y .mmdb de https://dev.maxmind.com/geoip/geoip2/geolite2/

 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 ?>