ios 测距信标仅在应用程序运行时有效?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19141779/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 01:58:26  来源:igfitidea点击:

Ranging Beacons only works when app running?

iosios7ibeacon

提问by Aaron Bratcher

I am having difficulties getting this to work for when the app is not running. I have locationManager:didRangeBeacons:inRegion:implemented and it is called when the app is running in the foreground or background, however it doesn't seem to do anything when I quit the app and lock the screen. The location services icon goes away and I never know that I entered a beacon range. Should the LocalNotification still work?

当应用程序没有运行时,我很难让它工作。我已经locationManager:didRangeBeacons:inRegion:实现并在应用程序在前台或后台运行时调用它,但是当我退出应用程序并锁定屏幕时它似乎没有做任何事情。定位服务图标消失了,我不知道我进入了信标范围。LocalNotification 还应该工作吗?

I have Location updates and Uses Bluetooth LE accessories selected in Background Modes (XCode 5) I didn't think I needed them.

我在后台模式 (XCode 5) 中选择了位置更新和使用蓝牙 LE 配件,我认为我不需要它们。

Any help greatly appreciated.

非常感谢任何帮助。

-(void)watchForEvents { // this is called from application:didFinishLaunchingWithOptions
    id class = NSClassFromString(@"CLBeaconRegion");
    if (!class) {
        return;
    }

    CLBeaconRegion * rflBeacon = [[CLBeaconRegion alloc] initWithProximityUUID:kBeaconUUID identifier:kBeaconString];
    rflBeacon.notifyOnEntry = YES;
    rflBeacon.notifyOnExit = NO;
    self.locationManager = [[CLLocationManager alloc] init];
    self.locationManager.delegate = self;
    [self.locationManager startRangingBeaconsInRegion:rflBeacon];
    [self.locationManager startMonitoringForRegion:rflBeacon];
}

-(void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region {
    if (beacons.count == 0 || eventRanged) { // breakpoint set here for testing
        return;
    }

    eventRanged = YES;
    if (backgroundMode) { // this is set in the EnterBackground/Foreground delegate calls
        UILocalNotification *notification = [[UILocalNotification alloc] init];
        notification.alertBody = [NSString stringWithFormat:@"Welcome to the %@ event.",region.identifier];
        notification.soundName = UILocalNotificationDefaultSoundName;
        [[UIApplication sharedApplication] presentLocalNotificationNow:notification];
    }

    // normal processing here...
}

回答by davidgyoung

Monitoring can launch an app that isn't running. Ranging cannot.

监控可以启动未运行的应用程序。测距不能。

The key to having monitoring launch your app is to set this poorly documented flag on your CLBeaconRegion: region.notifyEntryStateOnDisplay = YES;This can launch your app on a region transition even after completely rebooting your phone. But there are a couple of caveats:

监控启动您的应用程序的关键是在您的CLBeaconRegion:r上设置这个记录不佳的标志egion.notifyEntryStateOnDisplay = YES;即使在完全重新启动手机后,这也可以在区域转换时启动您的应用程序。但有几个警告:

  1. Your app launches into the background only for a few seconds. (Try adding NSLogstatements to applicationDidEnterBackgroundand other methods in your AppDelegate to see what is going on.)
  2. iOS can take its own sweet time to decide you entered a CLBeaconRegion. I have seen it take up to four minutes.
  1. 您的应用程序仅在几秒钟内启动到后台。(尝试在 AppDelegate 中添加NSLog语句applicationDidEnterBackground和其他方法以查看发生了什么。)
  2. iOS 可以花自己的时间来决定您是否输入了CLBeaconRegion. 我看到最多需要四分钟。

As far as ranging goes, even though you can't have ranging wake up your app, you can make your app do both monitoring and ranging simultaneously. If monitoring wakes up your app and puts it into the background for a few seconds, ranging callbacks start up immediately. This gives you a chance to do any quick ranging actions while your app is still running.

就测距而言,即使你不能让测距唤醒你的应用,你也可以让你的应用同时进行监测和测距。如果监控唤醒您的应用程序并将其置于后台几秒钟,则范围回调会立即启动。这使您有机会在您的应用程序仍在运行时执行任何快速测距操作。

EDIT: Further investigation proves that notifyEntryStateOnDisplayhas no effect on background monitoring, so the above should work regardless of whether you have this flag. See this detailed explanation and discussion of delays you may experience

编辑:进一步调查证明这notifyEntryStateOnDisplay对后台监控没有影响,因此无论您是否拥有此标志,上述内容都应该有效。请参阅有关您可能遇到的延迟的详细说明和讨论

回答by Teodor Ciuraru

Code for iOS 9 to range beacons in the background, by using Location Updates:

通过使用位置更新,iOS 9 的代码在后台对信标进行测距

  1. Open Project Settings -> Capabilities -> Background Modes -> Toggle Location Updatesand Uses Bluetooth LE accessoriesto ON.

  2. Create a CLLocationManager, request Alwaysmonitoring authorization (don't forget to add the Application does not run in backgroundto NOand NSLocationAlwaysUsageDescriptionin the app's info.plist) and set the following properties:

    locationManager!.delegate = self
    locationManager!.pausesLocationUpdatesAutomatically = false
    locationManager!.allowsBackgroundLocationUpdates = true
    
  3. Start ranging for beacons and monitoring region:

    locationManager!.startMonitoringForRegion(yourBeaconRegion)
    locationManager!.startRangingBeaconsInRegion(yourBeaconRegion)
    locationManager!.startUpdatingLocation()
    
    // Optionally for notifications
    UIApplication.sharedApplication().registerUserNotificationSettings(
        UIUserNotificationSettings(forTypes: .Alert, categories: nil))
    
  4. Implement the CLLocationManagerDelegateand in your didEnterRegionsend both startRangingBeaconsInRegion()and startUpdatingLocation()messages (optionally send the notification as well) and set the stopRangingBeaconsInRegion()and stopUpdatingLocation()in didExitRegion

  1. 打开 Project Settings -> Capabilities -> Background Modes -> Toggle Location Updatesand Uses Bluetooth LE accessoriesto ON

  2. 创建CLLocationManager,请求Always监控授权(不要忘记添加Application does not run in backgroundNO,并NSLocationAlwaysUsageDescription在应用程序的info.plist),并设置以下属性:

    locationManager!.delegate = self
    locationManager!.pausesLocationUpdatesAutomatically = false
    locationManager!.allowsBackgroundLocationUpdates = true
    
  3. 开始测距信标和监测区域:

    locationManager!.startMonitoringForRegion(yourBeaconRegion)
    locationManager!.startRangingBeaconsInRegion(yourBeaconRegion)
    locationManager!.startUpdatingLocation()
    
    // Optionally for notifications
    UIApplication.sharedApplication().registerUserNotificationSettings(
        UIUserNotificationSettings(forTypes: .Alert, categories: nil))
    
  4. 落实CLLocationManagerDelegate并在didEnterRegion同时发送startRangingBeaconsInRegion()startUpdatingLocation()消息(可选发送通知为好),并设置stopRangingBeaconsInRegion()stopUpdatingLocation()didExitRegion

Be aware that this solution works but it is not recommended by Apple due to battery consumption and customer privacy!

请注意,此解决方案有效,但由于电池消耗和客户隐私,Apple 不建议这样做!

More here: https://community.estimote.com/hc/en-us/articles/203914068-Is-it-possible-to-use-beacon-ranging-in-the-background-

更多信息:https: //community.estimote.com/hc/en-us/articles/203914068-Is-it-possible-to-use-beacon-ranging-in-the-background-

回答by manishnath

Here is the process you need to follow to range in background:

以下是您需要遵循的过程以在后台进行范围调整:

  1. For any CLBeaconRegionalways keep monitoring on, in background or foreground and keep notifyEntryStateOnDisplay = YES
  2. notifyEntryStateOnDisplaycalls locationManager:didDetermineState:forRegion:in background, so implement this delegate call...
  1. 对于任何CLBeaconRegion始终在后台或前台进行监控并保持notifyEntryStateOnDisplay = YES
  2. notifyEntryStateOnDisplaylocationManager:didDetermineState:forRegion:在后台调用,所以实现这个委托调用...

...like this:

...像这样:

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

   if (state == CLRegionStateInside) {


        //Start Ranging
        [manager startRangingBeaconsInRegion:region];
    }

   else{

        //Stop Ranging
        [manager stopRangingBeaconsInRegion:region];
    }

}

I hope this helps.

我希望这有帮助。

回答by James Frost

You are doing two separate operations here - 'ranging' beacons and monitoring for a region. You can monitor for a region in the background, but not range beacons.

您在这里执行两个单独的操作 - “测距”信标和监视一个区域。您可以在后台监控某个区域,但不能监控距离信标。

Therefore, your implementation of locationManager:didRangeBeacons:inRegion:won't get called in the background. Instead, your call to startMonitoringForRegionwill result in one / some of the following methods being called:

因此,您的实现locationManager:didRangeBeacons:inRegion:不会在后台调用。相反,您的调用startMonitoringForRegion将导致调用以下一个/某些方法:

– locationManager:didEnterRegion:
– locationManager:didExitRegion:
– locationManager:didDetermineState:forRegion:

These will get called in the background. You can at that point trigger a local notification, as in your original code.

这些将在后台调用。您可以在那时触发本地通知,就像在您的原始代码中一样。

回答by Tommy Devoy

Your app should currently wake up if you're just wanting to be notified when you enter a beacon region. The only background restriction I know of concerns actually hosting an iBeacon on an iOS device. In that case, the app would need to be physically open in the foreground. For that situation, you'd be better off just doing the straight CoreBluetooth CBPeripheralManagerimplementation. That way you'd have some advertising abilities in the background.

如果您只想在进入信标区域时收到通知,您的应用当前应该会被唤醒。我所知道的唯一背景限制是在 iOS 设备上实际托管 iBeacon。在这种情况下,应用程序需要在前台物理打开。对于这种情况,您最好直接CBPeripheralManager执行CoreBluetooth实现。这样你就会在后台有一些广告能力。