How to listen to lock / unlock phone events while the application is running in the background?

I want my application monitor to be locked and unlocked, and also when it becomes empty (after longer inactivity), all this while my application is not focused, but works in the background.

I easily get lock / unlock / empty events when the application is focused:

-(void) startListeningForPhoneLockEvent { NSLog(@"Start listening to lock/unlock and screen-goes-black events."); CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), (void*)self, lockStateChanged, CFSTR("com.apple.springboard.lockstate"), NULL, CFNotificationSuspensionBehaviorDeliverImmediately); CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), (void*)self, hasBlankedScreen, CFSTR("com.apple.springboard.hasBlankedScreen"), NULL, CFNotificationSuspensionBehaviorDeliverImmediately); } 

And callback functions:

 static void lockStateChanged( CFNotificationCenterRef center, void*observer, CFStringRef name, const void *object, CFDictionaryRef userInfo ) { NSLog(@"Lock event received!"); } static void hasBlankedScreen( CFNotificationCenterRef center, void*observer, CFStringRef name, const void *object, CFDictionaryRef userInfo ) { NSLog(@"Blanked screen event received!"); } 

I turned on the background mode:

  • Background fetch.

However, when the application goes into the background, it does not accept lock / unlock / blank screen events.

I tried using other background modes such as playing sound, location updates, etc., but the application still does not accept lock / unlock / blank screen events in the background.

I am not sure if this is really possible, or if I am doing something wrong.

I am testing it on a real device that is upgrading to iOS9 using the latest Xcode with the iOS9 SDK.

+6
source share
1 answer

Despite the fact that your application is configured to work in the background, it actually does not start if it does not have work. To run it in the background with a location update, follow these instructions from Ricky :

  • I run the location manager every 1 minute in the didUpdateLocations function.
  • I allow the location manager to receive data from the device for 10 seconds before turning it off (to save battery).

Partial code below:

 -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{ for(int i=0;i<locations.count;i++){ CLLocation * newLocation = [locations objectAtIndex:i]; CLLocationCoordinate2D theLocation = newLocation.coordinate; CLLocationAccuracy theAccuracy = newLocation.horizontalAccuracy; NSTimeInterval locationAge = -[newLocation.timestamp timeIntervalSinceNow]; if (locationAge > 30.0) continue; //Select only valid location and also location with good accuracy if(newLocation!=nil&&theAccuracy>0 &&theAccuracy<2000 &&(!(theLocation.latitude==0.0&&theLocation.longitude==0.0))){ self.myLastLocation = theLocation; self.myLastLocationAccuracy= theAccuracy; NSMutableDictionary * dict = [[NSMutableDictionary alloc]init]; [dict setObject:[NSNumber numberWithFloat:theLocation.latitude] forKey:@"latitude"]; [dict setObject:[NSNumber numberWithFloat:theLocation.longitude] forKey:@"longitude"]; [dict setObject:[NSNumber numberWithFloat:theAccuracy] forKey:@"theAccuracy"]; //Add the vallid location with good accuracy into an array //Every 1 minute, I will select the best location based on accuracy and send to server [self.shareModel.myLocationArray addObject:dict]; } } //If the timer still valid, return it (Will not run the code below) if (self.shareModel.timer) return; self.shareModel.bgTask = [BackgroundTaskManager sharedBackgroundTaskManager]; [self.shareModel.bgTask beginNewBackgroundTask]; //Restart the locationMaanger after 1 minute self.shareModel.timer = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:@selector(restartLocationUpdates) userInfo:nil repeats:NO]; //Will only stop the locationManager after 10 seconds, so that we can get some accurate locations //The location manager will only operate for 10 seconds to save battery NSTimer * delay10Seconds; delay10Seconds = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(stopLocationDelayBy10Seconds) userInfo:nil repeats:NO]; } 

I was able to use your code in the github project referenced to listen to the lock and unlock events on a device running ios 9 using the latest Xcode. Here are the logs:

  2015-12-18 13: 31: 44.777 Location [16185: 3796448] startLocationTracking
 2015-12-18 13: 31: 44.780 Location [16185: 3796448] authorizationStatus authorized
 2015-12-18 13: 31: 44.788 Location [16185: 3796448] Start listening to lock / unlock and screen-goes-black events.
 2015-12-18 13: 31: 44.834 Location [16185: 3796448] locationManager didUpdateLocations
 2015-12-18 13: 31: 44.837 Location [16185: 3796448] started master task 1
 2015-12-18 13: 31: 45.197 Location [16185: 3796448] locationManager didUpdateLocations
 2015-12-18 13: 31: 48.079 Location [16185: 3796448] Blanked screen event received!
 2015-12-18 13: 31: 48.215 Location [16185: 3796448] Lock event received! 
-1
source

All Articles