在后台扫描iOS信标的范围

6

I know that the main purposes of the

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

在应用程序前台工作。

在后台运行时,

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

用于检测信标,但提供的信息不如所需(从CLBeacons获取的次要和主要ID可提供上下文信息)。

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

是否可能做到这样: - 进入区域时短暂地在后台范围内的信标 - 根据次要/主要ID在后台调用Web服务 - 调度使用Web服务返回结果配置的UILocalNotification

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



}

我在一个应用程序中有类似的需求。你能想出一种方法来实现吗? - Chengappa C D
5个回答

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

回答你最初的问题:在后台模式下进行范围定位可能吗?答案是肯定的,但你应该尽快停止它。iOS 无论如何都会把定位停止,但保持范围定位将会耗费电池,并且没有意义。

我也有同样的问题。

  1. 在区域内识别主/次区域。
  2. 调用 Web 服务以获取更新的信息。
  3. 当监控 UUID 时,你不能检测到具有相同 UUID 的重叠信标的主/次区域更改。

我的解决方案如下:

  1. 监控UUID
  2. 一旦进入该区域,停止监控并开始测距以确定最近的信标。
  3. 一旦确定最近的信标(有时需要调用最多3次的测距代理方法),停止测距。
  4. 同时确定当前是否在后台模式下运行(可以看到,我在不询问运行模式的情况下进行了测距和停止测距)。
  5. 如果在前台模式下:显示包含信标信息的顶部横幅,并安排在3秒内进行另一次测距以侦测新的信标。
  6. 如果在后台模式下:发送本地通知。
  7. 在两种模式下都推迟网页服务调用,直到用户对通知采取行动。与此同时,从本地字典中选择信标呈现一个通用信息:"点击查看今天的特别促销活动"。

我知道这听起来很复杂,实际上确实如此。需要现场测试以微调它。它满足最低要求,而不依赖于快速的互联网连接。

我将尝试@ZhenHuiying提出的后台任务,如果信标是在室外,这似乎是可行的。在我这里,室内的手机信号不够可靠,无法在后台模式下显示更新的数据。


0

我尝试了一些在后台范围信标的东西,它对我有效,我希望它也能对你有效。

第一步:将此代码添加到应用程序 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{

我发现你的应用程序会在后台唤醒仅持续几秒钟,然后进入这个didDetermine state函数,所以在这几秒钟内,你调用beacon功能的范围函数,并在AppDelegate中实现其代理。
如果你需要帮助,告诉我。

0

你应该可以向 Web 服务发送请求,但不能保证可靠接收响应。你的应用程序仅在信标通知后保持唤醒约5秒钟。

也许可以请求后台时间以完成网络事务 - 我不是处理后台的专家。

无论如何,你需要用户解锁手机才能进行任何 UI 操作。为什么不让你的服务器响应信息并发送推送通知呢?这可以实现你所有的目标。


是的,但使用推送通知需要我们添加另一个抽象和技术层(证书等)。 因为我们希望提供一个可在已使用推送通知的现有应用程序中使用的跨行业框架,所以我对不使用它感兴趣。我已经在一个房地产应用上工作过:您步入一个城镇,使用startMonitoringSignificantLocationChanges检测您的位置,我们查找本地数据库中检索到的邮政编码的ID,在其中调用webservice,并显示具有属性数量的UILocalNotification。 - Romain Dorange

0

如果您确实需要响应您的 Web 服务调用以显示通知,则 @duncan-c 是正确的,因为在您的应用程序返回睡眠状态之前,它可能不会在 5 秒左右回答。

另一种选择是从您的 Web 服务向您的 iOS 设备发送 推送通知。这种方法的优点是即使您的应用程序已经返回睡眠状态,通知也会被传递到您的手机上。这种方法的缺点是推送通知的传递不是立即的,有时需要几分钟才能到达。您必须决定是否适用于您的用例。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接