Cómo usar los servicios de localización en segundo plano

Cómo usar los servicios de localización en segundo plano

Uno de los problemas más habituales a la hora de desarrollar apps que requieran el uso de los servicios de localización en iOS es que no podemos usarlos en segundo plano permanentemente. iOS mata las aplicaciones a los 10 minutos de estar en background. En este artículo os enseñaremos a evitar este molesto problema.

Servicios de localización en segundo plano

Comenzaremos incluyendo las librerías de localización y CLLocationManagerDelegate en nuestro MainViewController.h y declarando locationManager para que sea accesible:

import <CoreLocation/CoreLocation.h>

@interface MainViewController : UIViewController <CLLocationManagerDelegate> { }

CLLocationManager *locationManager;

Una vez tengamos esto, trabajaremos en MainViewController.m y añadiremos este bloque al principio del todo, antes de @implementation:

@interface AppDelegate : UIResponder <UIApplicationDelegate> + (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations; @end

En ViewDidLoad incluiremos el código que arrancará el sistema GPS de iOS 6:

locationManager.distanceFilter = 100; locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters; [locationManager startMonitoringSignificantLocationChanges]; [locationManager startUpdatingLocation];

En este caso lo que hemos hecho es poner el GPS en modo social para que consuma muy poca batería ajustando a 100 metros el filtro de distancia y la precisión a cientos de metros. Activamos, además, el modo SignificantLocationChanges para que el GPS se active sólo cuando se cumplan estas condiciones. Se pueden omitir estas tres líneas y usar tan sólo startUpdatingLocation para máxima precisión, pero la batería del dispositivo va a morir a un ritmo del 10% la hora.

La función didUpdateLocations se llamará cada vez que se produzca un cambio de localización.

  • (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { CLLocation *loc = [locations objectAtIndex:[locations count] – 1];

float latitudeMe = loc.coordinate.latitude; float longitudeMe = loc.coordinate.longitude; }

Con esto tendremos funcionando la localización, pero no en segundo plano. Para lograr este objetivo en el AppDelegate incluiremos estos cambios.

  • (void)applicationWillResignActive:(UIApplication *)application {

NSLog(@»to background»);

UIApplication *app = [UIApplication sharedApplication];

NSAssert(bgTask == UIBackgroundTaskInvalid, nil);

bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ dispatch_async(dispatch_get_main_queue(), ^{

if (bgTask != UIBackgroundTaskInvalid) { [app endBackgroundTask:bgTask]; bgTask = UIBackgroundTaskInvalid; } }); }];

// Start the long-running task and return immediately. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

locationManager.distanceFilter = 100; locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters; [locationManager startMonitoringSignificantLocationChanges]; [locationManager startUpdatingLocation];

NSLog(@»App staus: applicationDidEnterBackground»); dispatch_async(dispatch_get_main_queue(), ^{ if (bgTask != UIBackgroundTaskInvalid) { [app endBackgroundTask:bgTask]; bgTask = UIBackgroundTaskInvalid; } }); });

NSLog(@»backgroundTimeRemaining: %.0f», [[UIApplication sharedApplication] backgroundTimeRemaining]);

}

El bloque dispatch_asynch hará que cada cierto tiempo se reactiven los servicios de localización. De esta forma podremos lograr lo imposible y es que nuestra app viva en segundo plano 24/7.

NOTA: Este método NO funciona en XCODE 4.4 ya que requiere las librerías de iOS 6 pero una vez compilado funcionará en cualquier iOS 4, 5 ó 6 y iPhone 3GS, 4, 4S, 5 y iPad 2 y 3.

Comparte este artículo con tus amigos en Facebook, Google+ y Twitter con los botones que encontrarás al principio del mismo. ¡Gracias!