应用程序在后台运行时如何监听锁定/解锁手机事件?

Sin*_*isa 6 events multithreading objective-c ios

我想让我的应用程序监视器在手机锁定和解锁时,以及当它变为空白(经过较长时间不活动)后,这一切都在我的应用程序没有聚焦,但在后台运行时.

在应用专注时,我可以轻松收到锁定/解锁/空白事件:

-(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);
}
Run Code Online (Sandbox Code Playgroud)

和回调函数:

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!");
}
Run Code Online (Sandbox Code Playgroud)

我启用了后台模式:

  • 背景提取.

但是,一旦应用程序进入后台,它就不会收到锁定/解锁/空白屏幕事件.

我尝试过其他背景模式,如声音播放,位置更新等,但应用程序仍然没有在后台接收锁定/解锁/空白屏幕事件.

我不确定这是否真的可行,或者我做错了什么.

我正在使用最新的XCode和iOS9 SDK在真实设备上测试它,该设备已更新到iOS9.

小智 -1

即使您的应用程序配置为在后台运行,但如果没有要做的工作,它实际上不会运行。要让它在后台运行并进行位置更新,请按照 Ricky 的以下说明进行操作:

  1. 我在 function 中每 1 分钟重新启动一次位置管理器didUpdateLocations
  2. 我允许位置管理器在关闭设备之前从设备获取位置 10 秒(以节省电池)。

部分代码如下:

-(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];
 }
Run Code Online (Sandbox Code Playgroud)

我能够使用您在 github 项目中引用的代码,使用最新的 XCode 来监听运行 ios 9 的设备上的锁定和解锁事件。这是日志:

2015-12-18 13:31:44.777 位置[16185:3796448] 开始位置跟踪
2015-12-18 13:31:44.780 位置[16185:3796448] 授权状态已授权
2015-12-18 13:31:44.788 Location[16185:3796448] 开始监听锁定/解锁和屏幕变黑事件。
2015-12-18 13:31:44.834 位置[16185:3796448] locationManager didUpdateLocations
2015-12-18 13:31:44.837 Location[16185:3796448]开始主任务1
2015-12-18 13:31:45.197 位置[16185:3796448] locationManager didUpdateLocations
2015-12-18 13:31:48.079 Location[16185:3796448] 收到黑屏事件!
2015-12-18 13:31:48.215 Location[16185:3796448] 收到锁定事件!