背景中的测距信标

Ranging beacons in background

我想在后台响起信标。对于背景,我的意思是 phone 进入锁定屏幕时。我希望应用程序继续测距信标。我现在遇到的问题是代码永远找不到信标。我有两个正在工作的信标,但 AppDelegate 找不到它们。当我 运行 ViewController 中的相同代码时,它会找到信标并显示它们。我该怎么做?

@interface BDAppDelegate () <AXABeaconManagerDelegate>

@end

@implementation BDAppDelegate {
    NSMutableDictionary *beaconRegions;
    NSMutableDictionary *detectBeacons;
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application {
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
    CLBeaconRegion *beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:[[NSUUID alloc] initWithUUIDString:@"MyUUID"] identifier:@"微信"];

    [AXABeaconManager sharedManager].beaconDelegate = self;
    [[AXABeaconManager sharedManager] requestAlwaysAuthorization];
    [[AXABeaconManager sharedManager] startRangingBeaconsInRegion:beaconRegion];

    self->beaconRegions = [[NSMutableDictionary alloc] init];
    self->detectBeacons = [[NSMutableDictionary alloc] init];

    while (detectBeacons.count < 10) {
        NSLog(@"Rows in detectBeacons %lu", (unsigned long)beaconRegions.count);
    }

    self->beaconRegions[beaconRegion] = [NSArray array];
}

- (void)didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region {
    self->beaconRegions[region] = beacons;
    NSMutableArray *allBeacons = [NSMutableArray array];

    for (NSArray *regionResult in [self->beaconRegions allValues])
    {
        [allBeacons addObjectsFromArray:regionResult];
    }

    NSPredicate *pre = [NSPredicate predicateWithFormat:@"accuracy != -1"];

    NSArray *rights = [allBeacons filteredArrayUsingPredicate:pre];

    NSString * str = @"accuracy";
    self->detectBeacons[str] = rights;
}

@end

对于CLLocationManager有一个方法startMonitoringForRegion(CLBeaconRegion *):beaconRegion

应该在我们开始之前添加 startRangingBeaconsInRegion

因此,如果您的 AXABeaconManager class 来自 CLLocationManager,请添加:

[[AXABeaconManager sharedManager] startMonitoringForRegion:beaconRegion];

否则: 创建一个 CLLocationManager 对象 locationManager 并初始化它,然后像下面这样添加开始监控。

[self.locationManager startMonitoringForRegion:beaconRegion];

在你之前startRangingBeaconsInRegion

讨论:startMonitoringForRegion 您必须为每个要监控的区域调用此方法一次。如果应用程序已在监视具有相同标识符的现有区域,则旧区域将替换为新区域。您使用此方法添加的区域由您应用中的所有位置管理器对象共享并存储在 monitoredRegions 属性.

更多参考here

ranging for beacons 是一个消耗大量电池的操作,iOS 不允许你在 BG 中无休止地这样做(大部分时间. 在某些情况下,它有效)

你要做的就是打电话给 iOS 你正在做的 BG 工作:

 UIBackgroundTaskIdentifier token = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
     NSLog(@"Ranging for region %@ killed", region.identifier);
 }];
 if(token == UIBackgroundTaskInvalid) {
     NSLog(@"cant start background task");
 }

然后做任何事

完成后,调用 endBackgroundTask

在 iOS 上,应用程序在后台的范围限制为 5 秒。每次将应用程序置于后台或触发信标监视事件(进入区域/退出区域)时,都会重新启动此计时器。好消息是,您可以在每个事件发生后将后台信标的允许时间延长至 3 分钟。

我整理了一个博客 post 向您展示了如何操作 here.