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

时间:2015-09-21 09:31:43

标签: ios objective-c multithreading events

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

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

-(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);
}

回调函数:

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!");
}

我启用了后台模式:

  • 背景提取。

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

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

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

我正在使用iOS9 SDK的最新XCode更新到iOS9的真实设备上进行测试。

1 个答案:

答案 0 :(得分:-1)

即使你的应用程序配置为在后台运行,如果没有工作要做,它也不会实际运行。要让它在具有位置更新的后台运行,请按照these instructions by Ricky

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

    以下部分代码:

    -(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];
     }
    

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

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!