在背景中测试iOS信标

时间:2014-01-17 14:18:32

标签: ios objective-c background cllocationmanager ibeacon

我知道

的主要目的
-(void)locationManager:(CLLocationManager*)manager
       didRangeBeacons:(NSArray*)beacons
              inRegion:(CLBeaconRegion*)region

是应用程序在前台工作。

在后台,

- (void)locationManager:(CLLocationManager*)manager didEnterRegion:(CLRegion *)region

用于检测信标但没有所需的信息(来自CLBeacons的次要和主要ID以提供上下文信息)。

我知道CLLocationManager中的委托方法允许在后台运行简短的代码。

是否有可能做到这样的事情:   - 进入区域时,在背景中短暂开始范围信标   - 根据次要/主要ID在后台调用Web服务   - 调度UILocalNotification配置了webservice的返回结果

- (void)locationManager:(CLLocationManager*)manager didEnterRegion:(CLRegion *)region
{

    if (![region isKindOfClass:[CLBeaconRegion class]]) return;


    [locationManager startRangingBeaconsInRegion:(CLBeaconRegion*)region];

}

然后:

-(void)locationManager:(CLLocationManager*)manager
       didRangeBeacons:(NSArray*)beacons
              inRegion:(CLBeaconRegion*)region
{

    if (beacons.count == 0) return;

    CLBeacon *foundBeacon = [sortedBeacons firstObject];

    // DO STUFF IN BACKGROUND
    if ([[UIApplication sharedApplication] applicationState] != UIApplicationStateActive){
        //Call for a webservice according to minor /major

        //Dispatch contextual notification
        // ^success(...)
        UILocalNotification * theNotification = [[UILocalNotification alloc] init];
        theNotification.alertBody = [NSString stringWithFormat:@""];

        theNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:1];

        [[UIApplication sharedApplication] scheduleLocalNotification:theNotification];


    }
    else{   //DO STUFF IN FOREGROUND
        NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"proximity"
                                                                       ascending:YES];
        NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc] initWithKey:@"accuracy"
                                                                        ascending:YES];

        NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor,sortDescriptor2];
        NSArray *sortedBeacons = [beacons sortedArrayUsingDescriptors:sortDescriptors];
        //determine which beacon will be used to trigger foreground event
    }



}

5 个答案:

答案 0 :(得分:4)

我遇到了完全相同的情况。 我使用了以下模式:

// start background task
- (void)beginBackgroundTask {
    if (self.backgroundTask != UIBackgroundTaskInvalid) {
        [self endBackgroundTask];
    }

    self.backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
        [self endBackgroundTask];
    }];
}

// end background task
- (void)endBackgroundTask {
    if (self.backgroundTask != UIBackgroundTaskInvalid) {
        [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
    }
    self.backgroundTask = UIBackgroundTaskInvalid;
}

这些是我用来标记/取消标记后台任务的常规方法,例如调用Web服务。

以下是一些使用这些模式:

[self beginBackgroundTask];

[[MySessionManager sharedInstance] POST:MoteList parameters:params success:^(NSURLSessionDataTask *task, id responseObject) {
    // process the response

    [self endBackgroundTask];
} failure:^(NSURLSessionDataTask *task, NSError *error) {
    // error handling
}];

顺便说一下,这个后台任务时间限制在3分钟左右。

还可以选择无限期执行后台任务: 这是从iOS 7开始使用NSURLSession支持的多任务API。 但它可以只用于下载/上传任务。 如果需要执行POST请求,则服务器响应应该是可下载的json / xml数据。 应用程序应将其下载到文件中并以编程方式解析。

我希望这会对你有所帮助。

答案 1 :(得分:1)

回答您的原始问题:在后台模式下可以进行测距吗?答案是肯定的,但你应该尽快停止。 iOS无论如何都会阻止你,但保持测距会耗尽电池,但它没有意义。

我也有同样的问题。

  1. 识别某个地区的主要/次要。
  2. 致电网络服务以获取最新信息。
  3. 在监控UUID时,您无法检测具有相同UUID的重叠信标的主要/次要变化。
  4. 我的解决方案是这样的:

    1. 监控UUID
    2. 进入该地区后,停止监控并开始测距,以确定最近的信标。
    3. 一旦识别出最近的信标(有时在最多3次调用范围委托方法之后),停止测距。
    4. 此时,还要确定我们是否在后台模式下运行(正如您所看到的,我在不询问运行模式的情况下进行了测距并停止了测距)。
    5. 如果我们处于前台模式:我会显示带有信标信息的顶部横幅。并安排另一个范围在3秒内检测新的信标。
    6. 如果我们处于后台模式:我发送本地通知。
    7. 在这两种模式下,我都会推迟Web服务调用,直到用户对通知进行操作。在此期间,我显示从本地词典中选择的信标的通用消息:"触摸以查看今天的特殊促销活动"。
    8. 我知道这听起来很复杂,而且确实如此。它需要在现场测试中进行调整。它不满足最低要求,不依赖于快速的互联网连接。

      我将尝试@ZhenHuiying提出的后台任务,如果信标在户外,这听起来是可行的。就我而言,室内单元信号不够可靠,无法在后台模式下显示更新数据。

答案 2 :(得分:0)

您应该能够向Web服务发送请求,但您将无法可靠地收到响应。您的应用程序仅在信标通知后约5秒钟保持清醒状态。

可能会请求后台时间来完成您的网络交易 - 我不是后台处理专家。

无论如何,您需要用户解锁手机才能对UI执行任何操作。为什么不让服务器发送推送通知以回复您的消息?这实现了你的所有目标。

答案 3 :(得分:0)

如果你真的需要你的网络服务电话的响应来显示通知,那么@ duncan-c是正确的,它可能在你的应用程序重新进入睡眠状态之前的5秒内没有应答。

另一种方法是通过您的网络服务向您的iOS设备发送push notification。这种方法的优点是,即使您的应用程序已经重新入睡,它也会被发送到您的手机。这种方法的缺点是推送通知的传递不是立竿见影的 - 它们有时需要几分钟才能到达。您必须确定这是否适用于您的用例。

答案 4 :(得分:0)

我尝试在BackGrounds中放置信标,它对我有用,我希望它对你有用

第一步:在应用程序didFinishLaunchingWithOptions

中添加此代码
 _locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
[_locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[_locationManager setDistanceFilter:kCLDistanceFilterNone];
[_locationManager requestAlwaysAuthorization];


    _locationRegion=[[CLBeaconRegion alloc]
                     initWithProximityUUID:BLUE_SCENE
                     identifier:@"EstimoteSampleRegion"];

[_locationRegion setNotifyOnEntry:YES];
[_locationRegion setNotifyOnExit:YES];
[_locationRegion setNotifyEntryStateOnDisplay:YES];


[_locationManager startMonitoringForRegion:_locationRegion];

第二步:在此功能中再次添加此代码

-(void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region

并在此函数中

- (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region{

我发现你的应用程序会在后台唤醒一秒钟并进入此功能确定状态所以在这一秒你调用beacon功能并在AppDelegate中实现它的委托

如果您需要帮助,请告诉我