android - ubicado - ¿Dónde estoy?-Obtener país
satelite donde estoy yo (10)
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
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<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;
}
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.
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á :)
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).
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<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;
}
}
Iniciar sesión:
E / countryCode: IN
Editar: use Fused Location Provider para obtener la actualización de latitud y longitud para obtener mejores resultados.
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ó.
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, e.g.,
// "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
?>
/**
* 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;
}
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;
}