iBeacon: didRangeBeacons stops getting called, mus

2019-01-04 13:16发布

I am using a custom BeaconManager delegate so that beacon ranging is not determined by the life-cycle of the view controller. Everything works great but every once in a while (1-2 days) beacon ranging will stop working and didRangeBeacons will never get called. The only way to fix this is for me to reset my iPhone, once I do this, it works perfectly. Below is the code that I am using. The basic flow is that when my ViewController calls ViewDidLoad it sends a notification back to the AppDelegate to tell it to start ranging for beacons, I never tell it to stop then because I want it to continue to range for beacons no matter where the user navigates to in the app. I'm wondering if my code is causing this or if this is just a bug with Bluetooth. Thanks for your help!

BeaconManager.m

#import "BeaconManager.h"
#import "AppDelegate.h"

@interface BeaconManager()<CLLocationManagerDelegate>

@property (nonatomic, strong) CLLocationManager *locationManager;
@property (nonatomic, strong) CLBeaconRegion *beaconRegion;

@end

@implementation BeaconManager

+ (id)sharedManager
{
    static BeaconManager *sharedBeaconManager = nil;
    static dispatch_once_t once;
    dispatch_once(&once, ^{
        sharedBeaconManager = [[self alloc] init];
    });
    return sharedBeaconManager;
}

- (id)init
{
    self = [super init];
    if(self)
    {
        self.locationManager = [[CLLocationManager alloc] init];
        self.locationManager.delegate = self;
    }
    return self;
}

- (void)startBeaconMonitoring:(NSString*)forUUID
{
    NSUUID * uuid = [[NSUUID alloc] initWithUUIDString:forUUID];

    self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid identifier:@"com.beacons.publicRegion"];
    [self.locationManager startMonitoringForRegion:self.beaconRegion];
    [self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
}

- (void)stopBeaconMonitoring
{
    //Stop the region monitoring
    if(self.locationManager != nil && self.beaconRegion != nil) {
        [self.locationManager stopRangingBeaconsInRegion:self.beaconRegion];
    }
}

#pragma mark - CLLocationManagerDelegate

- (void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region
{
    self.beacons = beacons;
    if(self.delegate != nil) {
        [self.delegate beaconManager:self didRangeBeacons:self.beacons];
    }
}

@end

ViewController.m

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    [[NSNotificationCenter defaultCenter] postNotificationName:@"startRanging" object:nil userInfo:nil];
}

AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(startRangingForZombies) name:@"startRanging" object: nil];

    return YES;
}

- (void)startRanging
{
    //Start the beacon region monitoring when the controller loads
    BeaconManager *beaconManager = [BeaconManager sharedManager];
    beaconManager.delegate = self;
    [beaconManager startBeaconMonitoring:@"1234-54324-34242-34242-43243"];
}

5条回答
Fickle 薄情
2楼-- · 2019-01-04 13:35

I had the similar issue, but after some time of investigation I realized that it is wrong to call the startMonitoringForRegion(region) and startRangingBeaconsInRegion(region) after each other. That is what you (Patrick) do:

- (void)startBeaconMonitoring:(NSString*)forUUID {
     NSUUID * uuid = [[NSUUID alloc] initWithUUIDString:forUUID];

     self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid identifier:@"com.beacons.publicRegion"];
     [self.locationManager startMonitoringForRegion:self.beaconRegion];
     [self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
}

Instead the startRangingBeaconsInRegion(region) should to be called in the locationManagerDelegate method locationManager(manager: CLLocationManager!, didDetermineState state: CLRegionState, forRegion region: CLRegion!) (In this case the Swift code). This was my solution.

It make sense, because the first step is to find any beacon in the region, the second one is to get specific information from the already monitored beacon.

查看更多
Animai°情兽
3楼-- · 2019-01-04 13:54

We have received many reports at Radius Networks of phones stopping detecting iBeacons and requiring a reboot or turning Bluetooth off and back on again to resolve the situation. Folks have reported this on iPhone 4S, iPhone 5s, iPhone 5c and iPads.

I do not have any hard evidence that this is something that broke as of iOS 7.1, but the report frequency has gone way up since its release. The circumstantial evidence is therefore pretty strong.

When this phone gets into this state, the phone can still scan for bluetooth devices, and can still transmit as an iBeacon. It is therefore not a hardware problem with Bluetooth. Based on the available evidence, it is most likely a newly introduced bug in CoreLocation.

查看更多
Animai°情兽
4楼-- · 2019-01-04 13:54

Apple introduced important changes to Bluetooth LE in 7.1 but also broke something inside.

From my experiments:

  • iPhone 4S 7.x - iBeacons work like a charm

  • 2 x iPhone 4S 7.1, 2 x iPhone 5 7.1 - works fine but require restarts from time to time (undeterministic).

It looks like system issue - a big one. I have contacted Estimote - they know about it.

Interesting fact: You can't find beacons - even estimote demo app can't, delegate methods are not called but You can turn (broken)device into a beacon and it will be discovered by other devices.

查看更多
可以哭但决不认输i
5楼-- · 2019-01-04 13:55

Disclaimer: I currently work for sensorberg, we´re selling beacons and a SDK.

We´ve hat numerous reports of this bug as well. We asked all our customers to file a bug report with Apple. Here is a template that you can use: https://gist.github.com/anonymous/5283b6941e1f7d4e4461

I personally had the behaviour twice, once I was able to record it: https://www.youtube.com/watch?v=6a6IJzaxxJg Only restarting the device helped.

Continue to file Apple rdar bug reports!

查看更多
再贱就再见
6楼-- · 2019-01-04 13:58

Actually, it's a known bug in iOS 7.1. It's strictly a software problem with the Bluetooth stack for the latest version of iOS. Bluetooth devices detection sometimes just stops working - unfortunately, it's the case for all iOS 7.1-compatible devices. The bug has already been reported to Apple, but as long as they do not issue a fix for that, the best solution is to just reboot the device.

If reboot doesn't help, there is handy guide at SmartRobotic on how to solve it: http://www.smartbotics.com/#!4-Tips-to-Fix-Bluetooth-Problems-After-iOS-71-Upgrade/c118r/031A86F6-C8E8-4768-B4FD-E6F83D9E4317

If you are experiencing Bluetooth connectivity issues after upgrading to iOS 7.1, give these 4 tips a try.

  1. Shut down and restart - some people have reported that this is all that was needed to fix their device after the iOS 7.1 upgrade.
  2. Toggle Bluetooth OFF and back ON - Swipe up to access Control Center and tap the Bluetooth icon, wait at least 30 seconds, then toggle it back on. This can often repair a device which is experiencing connection issues.
  3. Kill (force quit) the offending app - Start by double clicking Home to launch the multitasking cards interface. Touch and hold the card for the app, then toss it up and away. This will force the app to quit and it will be fully reloaded the next time the app is opened.
  4. Clear and reset your Bluetooth device pairing - Go to Settings>Bluetooth and tap on the (i) icon for the offending device. Tap on Forget this Device. Now you should be able to re-add and re-pair the Bluetooth hardware to your device. To clear all paired devices, go to Settings > General > Reset > Reset Network Settings and then set up your Bluetooth pairings again.

Hopefully these suggestions will resolve your Bluetooth connectivity problems.

Cheers.

查看更多
登录 后发表回答