Android
Ubicación
Buscar..
Introducción
Las API de ubicación de Android se utilizan en una amplia variedad de aplicaciones para diferentes propósitos, como encontrar la ubicación del usuario, notificar cuando un usuario ha abandonado un área general (Geofencing) y ayudar a interpretar la actividad del usuario (caminar, correr, conducir, etc.).
Sin embargo, las API de ubicación de Android no son el único medio de adquirir la ubicación del usuario. Lo siguiente le dará ejemplos de cómo usar el LocationManager
de Android y otras bibliotecas de ubicación comunes.
Observaciones
Para crear aplicaciones conscientes de la ubicación en Android, hay dos caminos:
-
LocationManager
nativo de código abierto de Android -
FusedLocationProviderApi
de Google, que forma parte de los servicios de Google Play
Gerente de locación
Pros
- Control más granular.
- Disponible en todos los dispositivos.
- Parte del framework Android
Contras
- El consumo de la batería es un problema, si no se administra correctamente
- Requiere lógica para cambiar los proveedores de ubicación, si el dispositivo no puede encontrar una ubicación (por ejemplo, GPS deficiente dentro de un edificio)
Caracteristicas
- Oyente NMEA
- Escucha del estado del GPS
- Escuche los cambios de estado del proveedor (por ejemplo, el GPS está apagado por el usuario)
- Lista de proveedores para elegir la fuente de ubicación de
Proveedores
GPS
- Permisos requeridos:
- Precisión: 10m - 100m
- Requisitos de potencia: ALTA
- Disponibilidad: Mundial (con clara vista del cielo).
- NOTAS :
- Las actualizaciones de ubicación generalmente se realizan una vez por segundo, pero en situaciones donde el GPS no se ha utilizado durante un tiempo y el A-GPS no está disponible, puede tomar varios minutos para que se reciba una ubicación.
- En los casos en que se obstruye la vista clara del cielo, los puntos GPS no se agruparán muy bien (los puntos de ubicación "saltan") y la precisión puede ser engañosa en ciertas áreas debido al efecto del " Cañón urbano ".
Red
- Permisos requeridos:
- Precisión: 100m - 1000m +
- Requisitos de alimentación: BAJO - MEDIO
- Disponibilidad: Dentro del rango de torre celular o señal wifi.
- NOTAS:
- Las actualizaciones de ubicación ocurren con menos frecuencia que el GPS
- Las actualizaciones de ubicación generalmente no se agrupan bien (los puntos de ubicación "saltan") y la precisión puede variar según el número de factores diferentes (número de señales wifi, intensidad de la señal, tipo de torre celular, etc.)
Pasivo
- Permisos requeridos:
- Precisión: 10m - 1000m +
- Requisitos de alimentación: NINGUNO
- Disponibilidad: solo cuando otra aplicación recibe una ubicación de GPS o red
- NOTAS:
- No confíe en esto para darle actualizaciones continuas. Esto escucha de forma pasiva a otras aplicaciones que realizan solicitudes de ubicación y devuelve esas ubicaciones.
- No devuelve los puntos generados por FusedLocationProviderApi, solo los puntos de ubicación subyacentes utilizados para generarlos.
FusedLocationProviderApi
Pros
- Ofrece menos consumo de batería "fuera de la caja"
- Maneja bien el mal GPS
- Recibe actualizaciones más regularmente
Contras
- Menos control granular sobre GPS
- Puede no estar disponible en todos los dispositivos o en ciertos países
- Requiere dependencia de biblioteca de terceros
Caracteristicas
- Uso bien administrado de los proveedores de ubicación para un ahorro óptimo de la masa
- Normalmente genera puntos más precisos que el proveedor de ubicación de red
- Actualizaciones más frecuentes de la biblioteca, permitiendo más mejoras.
- No es necesario especificar qué tipo de proveedor utilizar
UbicaciónSolicitud de Niveles de Prioridad
PRIORITY_HIGH_ACCURACY
- Permisos requeridos:
-
ACCESS_FINE_LOCATION
para una ubicación más precisa oACCESS_COARSE_LOCATION
para una ubicación menos precisa
-
- Precisión: 10m - 100m
- Requisitos de potencia: ALTA
- Disponibilidad: Dondequiera que esté disponible Google Play Services.
- NOTAS:
- Si no se usa
ACCESS_FINE_LOCATION
, esto no usará el GPS para generar actualizaciones de ubicación, pero seguirá encontrando un punto bastante preciso en las condiciones correctas. - Si se usa
ACCESS_FINE_LOCATION
, puede o no usar GPS para generar puntos de ubicación, dependiendo de la precisión con la que actualmente puede rastrear el dispositivo dadas las condiciones ambientales. - Aunque esto puede reportar actualizaciones de ubicación más precisas que las otras configuraciones, todavía es propenso al efecto " Urban Canyon ".
- Si no se usa
PRIORITY_BALANCED_POWER_ACCURACY
- Permisos requeridos:
-
ACCESS_FINE_LOCATION
para una ubicación más precisa oACCESS_COARSE_LOCATION
para una ubicación menos precisa
-
- Precisión: 100m - 1000m +
- Requisitos de energía: MEDIO
- Disponibilidad: Dondequiera que esté disponible Google Play Services.
- NOTAS:
- Las mismas notas que
PRIORITY_HIGH_ACCURACY
- Aunque es poco probable, esta configuración puede seguir utilizando el GPS para generar una ubicación.
- Las mismas notas que
PRIORITY_LOW_POWER
- Permisos requeridos:
- Precisión: 100m - 1000m +
- Requisitos de alimentación: BAJA
- Disponibilidad: Dondequiera que esté disponible Google Play Services.
- NOTAS:
- Probablemente no use GPS, pero no está probado hasta ahora.
- Las actualizaciones no suelen ser muy precisas
- Usado generalmente para detectar cambios significativos en la ubicación.
PRIORITY_NO_POWER
- Permisos requeridos:
- Precisión: 10m - 1000m +
- Requisitos de alimentación: NINGUNO
- Disponibilidad: Dondequiera que esté disponible Google Play Services.
- NOTAS:
- Funciona de forma casi idéntica al
LocationManager
PASSIVE_PROVIDER
- Informa sobre las actualizaciones de Google Play Services cuando se recibe, donde
PASSIVE_PROVIDER
informa sobre las actualizaciones de ubicación subyacentes utilizadas
- Funciona de forma casi idéntica al
Solución de problemas
OnLocationChanged () nunca llamado
Ya que este parece ser un problema común con la obtención de ubicaciones de Android, pondré una lista rápida de correcciones comunes:
Revisa tu manifiesto!
Uno de los problemas más comunes es que nunca se dieron los permisos correctos. Si está utilizando GPS (con o sin red), use
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
, o use<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
. FusedLocationApi de Google requiereACCESS_FINE_LOCATION
.
(Para Android 6+) Verifique los permisos de tiempo de ejecución !
Compruebe y solicite permisos! Si nunca te dan permisos, terminarás con colisiones o, lo que es peor (si estás detectando todas las excepciones), ¡terminarás sin ninguna indicación de nada! No importa si el usuario le otorga permiso al inicio de la aplicación, siempre verifique si tiene permisos para todas las llamadas. El usuario puede acceder fácilmente a sus ajustes y revocarlos.
¡Comprueba tu código!
¿Estás seguro de que estás pasando en el oyente correcto? ¿
IntentService
eseBroadcastReceiver
oIntentService
a su manifiesto? ¿Está utilizandoPendingIntent.getService()
en una claseBroadcastReceiver
, ogetBroadcast()
en una claseIntentService
? ¿Está seguro de que no está desregistrando a su oyente en otra parte de su código inmediatamente después de realizar la solicitud?
Compruebe la configuración del dispositivo!
Obviamente, asegúrate de tener los servicios de ubicación activados.
Si está utilizando servicios de red, ¿activó "Escanear siempre disponible"? ¿Tiene el modo de ubicación configurado en "Mejor" ("Alta precisión") o "Ahorro de batería" ("Sólo en red")?
Si está utilizando GPS, ¿activó "Mejor" ("Alta precisión") o "Solo dispositivo" en el modo de ubicación?
¡Comprueba tu código!
Sí, esto está aquí dos veces. ¿
PendingIntent
usar unLocationListener
lugar de unPendingIntent
, o viceversa, para asegurarse de que realmente implementó elLocationManager
correctamente? ¿Está seguro de que la solicitud de ubicación no se está eliminando en alguna parte del ciclo de vida de la actividad o el servicio que no esperaba que ocurriera?
Revisa tu entorno!
¿Está probando el GPS en el primer piso de un edificio en el centro de San Francisco? ¿Está probando ubicaciones de red en medio de la nada? ¿Trabaja en un búnker subterráneo secreto sin todas las señales de radio, preguntándose por qué su dispositivo no tiene ubicación? ¡Siempre revise dos veces sus alrededores cuando intente solucionar problemas de ubicación!
Podría haber muchas otras razones menos obvias por las que la ubicación no funciona, pero antes de buscar esas correcciones esotéricas, simplemente ejecute esta lista de verificación rápida.
API de ubicación fusionada
Ejemplo de uso de la actividad con LocationRequest
/*
* This example is useful if you only want to receive updates in this
* activity only, and have no use for location anywhere else.
*/
public class LocationActivity extends AppCompatActivity implements
GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mLocationRequest = new LocationRequest()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY) //GPS quality location points
.setInterval(2000) //At least once every 2 seconds
.setFastestInterval(1000); //At most once a second
}
@Override
protected void onStart(){
super.onStart();
mGoogleApiClient.connect();
}
@Override
protected void onResume(){
super.onResume();
//Permission check for Android 6.0+
if(ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
if(mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
}
}
@Override
protected void onPause(){
super.onPause();
//Permission check for Android 6.0+
if(ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
if(mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
}
}
@Override
protected void onStop(){
super.onStop();
mGoogleApiClient.disconnect();
}
@Override
public void onConnected(@Nullable Bundle bundle) {
if(ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
}
@Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}
@Override
public void onLocationChanged(Location location) {
//Handle your location update code here
}
}
Ejemplo de uso de Service w / PendingIntent y BroadcastReceiver
EjemploActividad
Lectura recomendada: LocalBroadcastManager
/*
* This example is useful if you have many different classes that should be
* receiving location updates, but want more granular control over which ones
* listen to the updates.
*
* For example, this activity will stop getting updates when it is not visible, but a database
* class with a registered local receiver will continue to receive updates, until "stopUpdates()" is called here.
*
*/
public class ExampleActivity extends AppCompatActivity {
private InternalLocationReceiver mInternalLocationReceiver;
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
//Create internal receiver object in this method only.
mInternalLocationReceiver = new InternalLocationReceiver(this);
}
@Override
protected void onResume(){
super.onResume();
//Register to receive updates in activity only when activity is visible
LocalBroadcastManager.getInstance(this).registerReceiver(mInternalLocationReceiver, new IntentFilter("googleLocation"));
}
@Override
protected void onPause(){
super.onPause();
//Unregister to stop receiving updates in activity when it is not visible.
//NOTE: You will still receive updates even if this activity is killed.
LocalBroadcastManager.getInstance(this).unregisterReceiver(mInternalLocationReceiver);
}
//Helper method to get updates
private void requestUpdates(){
startService(new Intent(this, LocationService.class).putExtra("request", true));
}
//Helper method to stop updates
private void stopUpdates(){
startService(new Intent(this, LocationService.class).putExtra("remove", true));
}
/*
* Internal receiver used to get location updates for this activity.
*
* This receiver and any receiver registered with LocalBroadcastManager does
* not need to be registered in the Manifest.
*
*/
private static class InternalLocationReceiver extends BroadcastReceiver{
private ExampleActivity mActivity;
InternalLocationReceiver(ExampleActivity activity){
mActivity = activity;
}
@Override
public void onReceive(Context context, Intent intent) {
final ExampleActivity activity = mActivity;
if(activity != null) {
LocationResult result = intent.getParcelableExtra("result");
//Handle location update here
}
}
}
}
Servicio de localización
NOTA: ¡No olvides registrar este servicio en el Manifiesto!
public class LocationService extends Service implements
GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
@Override
public void onCreate(){
super.onCreate();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mLocationRequest = new LocationRequest()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY) //GPS quality location points
.setInterval(2000) //At least once every 2 seconds
.setFastestInterval(1000); //At most once a second
}
@Override
public int onStartCommand(Intent intent, int flags, int startId){
super.onStartCommand(intent, flags, startId);
//Permission check for Android 6.0+
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
if (intent.getBooleanExtra("request", false)) {
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, getPendingIntent());
} else {
mGoogleApiClient.connect();
}
}
else if(intent.getBooleanExtra("remove", false)){
stopSelf();
}
}
return START_STICKY;
}
@Override
public void onDestroy(){
super.onDestroy();
if(mGoogleApiClient.isConnected()){
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, getPendingIntent());
mGoogleApiClient.disconnect();
}
}
private PendingIntent getPendingIntent(){
//Example for IntentService
//return PendingIntent.getService(this, 0, new Intent(this, **YOUR_INTENT_SERVICE_CLASS_HERE**), PendingIntent.FLAG_UPDATE_CURRENT);
//Example for BroadcastReceiver
return PendingIntent.getBroadcast(this, 0, new Intent(this, LocationReceiver.class), PendingIntent.FLAG_UPDATE_CURRENT);
}
@Override
public void onConnected(@Nullable Bundle bundle) {
//Permission check for Android 6.0+
if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, getPendingIntent());
}
}
@Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
UbicaciónReceptor
NOTA: ¡No olvides registrar este receptor en el Manifiesto!
public class LocationReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if(LocationResult.hasResult(intent)){
LocationResult locationResult = LocationResult.extractResult(intent);
LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("googleLocation").putExtra("result", locationResult));
}
}
}
Solicitando actualizaciones de ubicación usando LocationManager
Como siempre, debe asegurarse de tener los permisos necesarios.
public class MainActivity extends AppCompatActivity implements LocationListener{
private LocationManager mLocationManager = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
}
@Override
protected void onResume() {
super.onResume();
try {
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
}
catch(SecurityException e){
// The app doesn't have the correct permissions
}
}
@Override
protected void onPause() {
try{
mLocationManager.removeUpdates(this);
}
catch (SecurityException e){
// The app doesn't have the correct permissions
}
super.onPause();
}
@Override
public void onLocationChanged(Location location) {
// We received a location update!
Log.i("onLocationChanged", location.toString());
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
}
Solicitar actualizaciones de ubicación en un subproceso separado utilizando LocationManager
Como siempre, debe asegurarse de tener los permisos necesarios.
public class MainActivity extends AppCompatActivity implements LocationListener{
private LocationManager mLocationManager = null;
HandlerThread mLocationHandlerThread = null;
Looper mLocationHandlerLooper = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
mLocationHandlerThread = new HandlerThread("locationHandlerThread");
}
@Override
protected void onResume() {
super.onResume();
mLocationHandlerThread.start();
mLocationHandlerLooper = mLocationHandlerThread.getLooper();
try {
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this, mLocationHandlerLooper);
}
catch(SecurityException e){
// The app doesn't have the correct permissions
}
}
@Override
protected void onPause() {
try{
mLocationManager.removeUpdates(this);
}
catch (SecurityException e){
// The app doesn't have the correct permissions
}
mLocationHandlerLooper = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2)
mLocationHandlerThread.quitSafely();
else
mLocationHandlerThread.quit();
mLocationHandlerThread = null;
super.onPause();
}
@Override
public void onLocationChanged(Location location) {
// We received a location update on a separate thread!
Log.i("onLocationChanged", location.toString());
// You can verify which thread you're on by something like this:
// Log.d("Which thread?", Thread.currentThread() == Looper.getMainLooper().getThread() ? "UI Thread" : "New thread");
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
}
Registrar geofence
He creado la clase de GeoFenceObserversationService
singleton .
GeoFenceObserversationService.java :
public class GeoFenceObserversationService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, ResultCallback<Status> {
protected static final String TAG = "GeoFenceObserversationService";
protected GoogleApiClient mGoogleApiClient;
protected ArrayList<Geofence> mGeofenceList;
private boolean mGeofencesAdded;
private SharedPreferences mSharedPreferences;
private static GeoFenceObserversationService mInstant;
public static GeoFenceObserversationService getInstant(){
return mInstant;
}
@Override
public void onCreate() {
super.onCreate();
mInstant = this;
mGeofenceList = new ArrayList<Geofence>();
mSharedPreferences = getSharedPreferences(AppConstants.SHARED_PREFERENCES_NAME, MODE_PRIVATE);
mGeofencesAdded = mSharedPreferences.getBoolean(AppConstants.GEOFENCES_ADDED_KEY, false);
buildGoogleApiClient();
}
@Override
public void onDestroy() {
mGoogleApiClient.disconnect();
super.onDestroy();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
protected void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
@Override
public void onConnected(Bundle connectionHint) {
}
@Override
public void onConnectionFailed(ConnectionResult result) {
}
@Override
public void onConnectionSuspended(int cause) {
}
private GeofencingRequest getGeofencingRequest() {
GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER);
builder.addGeofences(mGeofenceList);
return builder.build();
}
public void addGeofences() {
if (!mGoogleApiClient.isConnected()) {
Toast.makeText(this, getString(R.string.not_connected), Toast.LENGTH_SHORT).show();
return;
}
populateGeofenceList();
if(!mGeofenceList.isEmpty()){
try {
LocationServices.GeofencingApi.addGeofences(mGoogleApiClient, getGeofencingRequest(), getGeofencePendingIntent()).setResultCallback(this);
} catch (SecurityException securityException) {
securityException.printStackTrace();
}
}
}
public void removeGeofences() {
if (!mGoogleApiClient.isConnected()) {
Toast.makeText(this, getString(R.string.not_connected), Toast.LENGTH_SHORT).show();
return;
}
try {
LocationServices.GeofencingApi.removeGeofences(mGoogleApiClient,getGeofencePendingIntent()).setResultCallback(this);
} catch (SecurityException securityException) {
securityException.printStackTrace();
}
}
public void onResult(Status status) {
if (status.isSuccess()) {
mGeofencesAdded = !mGeofencesAdded;
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putBoolean(AppConstants.GEOFENCES_ADDED_KEY, mGeofencesAdded);
editor.apply();
} else {
String errorMessage = AppConstants.getErrorString(this,status.getStatusCode());
Log.i("Geofence", errorMessage);
}
}
private PendingIntent getGeofencePendingIntent() {
Intent intent = new Intent(this, GeofenceTransitionsIntentService.class);
return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
private void populateGeofenceList() {
mGeofenceList.clear();
List<GeoFencingResponce> geoFenceList = getGeofencesList;
if(geoFenceList!=null&&!geoFenceList.isEmpty()){
for (GeoFencingResponce obj : geoFenceList){
mGeofenceList.add(obj.getGeofence());
Log.i(TAG,"Registered Geofences : " + obj.Id+"-"+obj.Name+"-"+obj.Lattitude+"-"+obj.Longitude);
}
}
}
}
AppConstant :
public static final String SHARED_PREFERENCES_NAME = PACKAGE_NAME + ".SHARED_PREFERENCES_NAME";
public static final String GEOFENCES_ADDED_KEY = PACKAGE_NAME + ".GEOFENCES_ADDED_KEY";
public static final String DETECTED_GEOFENCES = "detected_geofences";
public static final String DETECTED_BEACONS = "detected_beacons";
public static String getErrorString(Context context, int errorCode) {
Resources mResources = context.getResources();
switch (errorCode) {
case GeofenceStatusCodes.GEOFENCE_NOT_AVAILABLE:
return mResources.getString(R.string.geofence_not_available);
case GeofenceStatusCodes.GEOFENCE_TOO_MANY_GEOFENCES:
return mResources.getString(R.string.geofence_too_many_geofences);
case GeofenceStatusCodes.GEOFENCE_TOO_MANY_PENDING_INTENTS:
return mResources.getString(R.string.geofence_too_many_pending_intents);
default:
return mResources.getString(R.string.unknown_geofence_error);
}
}
¿Dónde empecé servicio? De la clase de aplicación
-
startService(new Intent(getApplicationContext(),GeoFenceObserversationService.class));
¿Cómo me registré Geofences?
-
GeoFenceObserversationService.getInstant().addGeofences();
Obtener la dirección de la ubicación utilizando Geocoder
Después de obtener el objeto de Location
de FusedAPI
, puede adquirir fácilmente la información de Address
de ese objeto.
private Address getCountryInfo(Location location) {
Address address = null;
Geocoder geocoder = new Geocoder(getActivity(), Locale.getDefault());
String errorMessage;
List<Address> addresses = null;
try {
addresses = geocoder.getFromLocation(
location.getLatitude(),
location.getLongitude(),
// In this sample, get just a single address.
1);
} catch (IOException ioException) {
// Catch network or other I/O problems.
errorMessage = "IOException>>" + ioException.getMessage();
} catch (IllegalArgumentException illegalArgumentException) {
// Catch invalid latitude or longitude values.
errorMessage = "IllegalArgumentException>>" + illegalArgumentException.getMessage();
}
if (addresses != null && !addresses.isEmpty()) {
address = addresses.get(0);
}
return country;
}
Obteniendo actualizaciones de ubicación en un BroadcastReceiver
Primero cree una clase BroadcastReceiver para manejar las actualizaciones de ubicación entrantes:
public class LocationReceiver extends BroadcastReceiver implements Constants {
@Override
public void onReceive(Context context, Intent intent) {
if (LocationResult.hasResult(intent)) {
LocationResult locationResult = LocationResult.extractResult(intent);
Location location = locationResult.getLastLocation();
if (location != null) {
// Do something with your location
} else {
Log.d(LocationReceiver.class.getSimpleName(), "*** location object is null ***");
}
}
}
}
Luego, cuando se conecte a GoogleApiClient en la devolución de llamada onConnected:
@Override
public void onConnected(Bundle connectionHint) {
Intent backgroundIntent = new Intent(this, LocationReceiver.class);
mBackgroundPendingIntent = backgroundPendingIntent.getBroadcast(getApplicationContext(), LOCATION_REUEST_CODE, backgroundIntent, PendingIntent.FLAG_CANCEL_CURRENT);
mFusedLocationProviderApi.requestLocationUpdates(mLocationClient, mLocationRequest, backgroundPendingIntent);
}
No olvide eliminar el intento de actualización de la ubicación en la devolución de llamada del ciclo de vida apropiado:
@Override
public void onDestroy() {
if (servicesAvailable && mLocationClient != null) {
if (mLocationClient.isConnected()) {
fusedLocationProviderApi.removeLocationUpdates(mLocationClient, backgroundPendingIntent);
// Destroy the current location client
mLocationClient = null;
} else {
mLocationClient.unregisterConnectionCallbacks(this);
mLocationClient = null;
}
}
super.onDestroy();
}