我花了几个月的时间开发基于iBeacons的应用程序,我真的感到很沮丧。
一般的想法是,当检测到信标时,将通知用户特定于该iBeacon的信息。
该应用程序的设计如下,所有iBeacons都具有相同的UUID,Major决定建筑物(博物馆,商店......)和Minor特定产品(图片,鞋子......)。因此,此应用程序可以为多个客户提供服务。
当应用程序启动时,我开始使用我们的UUID对区域进行监视和测距。当应用程序处于前台时,一切都很完美。但是在背景或暂停状态下,问题就开始了。在背景或暂停状态下不允许测距。
我知道当您进入或退出信标区域时,应用程序将在后台启动约5秒钟。你可以在这五秒钟内完成后续操作,之后iOS会再次暂停你的应用程序。
我设法通过这里学到的技术在后台扩展了最多3分钟。我还通过notifyEntryStateOnDisplay = YES;
获得额外的回调但这还不够,如果客户进入应用程序处于后台或暂停状态的区域,他将收到通知。在额外的3分钟内,如果测距检测到另一个iBeacon,他会收到通知,但是当3分钟后台任务到期时,如果没有触发任何区域退出,他将不会再收到任何通知。
在这样的场景中没有真正的解决方案吗?我认为这是一种非常常见的情况,我很惊讶没办法处理它。
编辑:我试图通过监测两个地区作为推荐的David Young在他的回答中找到问题的解决方案。为了获得更多的进入/退出地区事件。
我添加了我实现的代码,试图监控两个区域。
但是我做错了而且doRangeBeacons:InRegion:当预期的每秒钟时,回调每10毫秒触发一次。
在AppDelegate.m
上,我在didFinishLaunchingWithOptions:
[self.locationManager startMonitoringForRegion:self.beaconRegion];
[self.locationManager stopRangingBeaconsInRegion:self.beaconRegion];
[self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
[self.locationManager startMonitoringForRegion:self.beaconRegion2];
[self.locationManager stopRangingBeaconsInRegion:self.beaconRegion2];
[self.locationManager startRangingBeaconsInRegion:self.beaconRegion2];
然后,在didRangeBeacons:InRegion:
- (void) locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region{
if(beacons.count > 0){
[self.locationManager stopRangingBeaconsInRegion:region];
for (CLBeacon *beacon in beacons){
NSLog(@"beacon detected major: %@ minor: %@", beacon.major,beacon.minor);
}
[self.locationManager startRangingBeaconsInRegion:region];
}
}
当我在模拟器上运行应用程序,并且每个网络的信标都在范围内时,大约每10毫秒就会在控制台上显示该消息。
我怀疑停止并重新启动测距是打破预期的回调流程,但当只有一个区域在范围内时,回调会按预期每秒发生。
答案 0 :(得分:7)
您描述的问题很常见。除了延长背景测距时间(您已经完成), iOS上没有灵丹妙药。
另外两种技术可能会有所帮助。这两种技术都涉及在从一个信标传递到下一个信标时获得新条目事件:
获取硬件信标,让您调低发射机功率(我公司的RadBeacon产品允许这样做),因此传输不会重叠。这样,当您从信标移动到信标时,您将获得退出事件,然后是新的输入事件。
重新设计您的标识符示意图,以便主要字段专用于识别多达20个不同的区域(基于UUID和主要1-20)。然后,您监控所有这些区域。您的个人信标仍然可以根据需要使用未成年人,特别是作为触发消息传递的密钥。放置信标时,请确保没有重叠传输的信号共享相同的主信号。这将确保您从一个事件移动到另一个事件时的新背景事件。
答案 1 :(得分:2)
如果您跳过所有的环节,背景中的Beacon范围在iOS 8上运行正常。
首先,您需要正确的授权。将密钥NSLocationAlwaysUsageDescription
添加到您的Info.plist,然后调用
[self.locationManager requestAlwaysAuthorization];
您的应用必须Background Mode
Location Updates
。在Info.plist中指定或通过功能指定(与Build Settings并行)。
然后使用
检查applicationDidBecomeActive
中的授权
switch([CLLocationManager authorizationStatus])
{
...
获得授权后,您需要执行以下操作:
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
// If you don't do this, location updates will pause after 15 minutes in the same place
// Usually this is what you want, so I've left this line commented out
// self.locationManager.pausesLocationUpdatesAutomatically = NO;
// Create a NSUUID with the same UUID as the broadcasting beacon
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:kProximityUUID];
_beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid
identifier:@"uk.co.airsource.testregion"];
// Necessary to get continued background ranging.
// See https://community.estimote.com/hc/en-us/articles/203914068-Is-it-possible-to-use-beacon-ranging-in-the-background-
_locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
[_locationManager startUpdatingLocation];
[_locationManager startMonitoringForRegion:self.beaconRegion];