简体   繁体   中英

iPhone4S strange behavior at Beacon detection

I'm developing app that includes ibeacon detection.
But, when device receiving beacon A after B in background, nothing happened.

Condition
1. iPhone4S(iPhone5 is all ok)
2. App is in background
3. After detection of another beacon(different BeaconRegion from another one).

Can someone help me? Any suggestion would be appreciated.

Thank you for replying. Entering the area of Beacon A(second one) is delayed about 30 seconds from Entering the area of Beacon B(first one), and I waited about 20 seconds for LocalNotification that will be fired by "Beacon A". (Beacon-A area and Beacon-B area overlap each other partially. And I waited in the overlapped area.)

This is piece of code.

- (void)startBeaconMonitoring
{
    if ([CLLocationManager respondsToSelector:@selector(isMonitoringAvailableForClass:)] && [CLLocationManager isMonitoringAvailableForClass:[CLBeaconRegion class]] && !self.locationManager) {
        self.locationManager = [CLLocationManager new];
        self.locationManager.delegate = self;

        _storeUUID = [[NSUUID alloc] initWithUUIDString:@"MY UUID HERE"];
        CLBeaconRegion *region = [[CLBeaconRegion alloc] initWithProximityUUID:_storeUUID major:CENSOR_TYPE_A  identifier:@"MY ID1"];
        region.notifyOnExit  = YES;
        region.notifyOnEntry = YES;

        CLBeaconRegion *region2 = [[CLBeaconRegion alloc] initWithProximityUUID:_storeUUID major:CENSOR_TYPE_B identifier:@"MY ID2"];
        region.notifyOnExit  = YES;
        region.notifyOnEntry = YES;

        [self.locationManager startMonitoringForRegion:region];
        [self.locationManager startMonitoringForRegion:region2];
    }
}

# pragma CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region
{
    [self.locationManager requestStateForRegion:region];
}

- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
    if ([region isMemberOfClass:[CLBeaconRegion class]] && [CLLocationManager isRangingAvailable]) {
        CLBeaconRegion *beacon = (CLBeaconRegion*)region;
        [self.locationManager startRangingBeaconsInRegion:beacon];
    }
}

- (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region
{
    switch (state) {
        case CLRegionStateInside:
            if ([region isMemberOfClass:[CLBeaconRegion class]] && [CLLocationManager isRangingAvailable]) {
                CLBeaconRegion *beacon = (CLBeaconRegion*)region;
                int major = [beacon.major intValue];
                [self.locationManager startRangingBeaconsInRegion:beacon];
            }
            break;
        case CLRegionStateOutside:
        case CLRegionStateUnknown:
        default:
            break;
    }
}

- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{
    if ([region isMemberOfClass:[CLBeaconRegion class]] && [CLLocationManager isRangingAvailable]) {
        [self.locationManager stopRangingBeaconsInRegion:(CLBeaconRegion *)region];
    }
}

- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
    switch (status) {
        case kCLAuthorizationStatusAuthorized:
            if (_locationDisabled) {
                _locationDisabled = NO;
                self.locationManager = nil;
                [self startBeaconMonitoring];
            }
            break;
        case kCLAuthorizationStatusRestricted:
        case kCLAuthorizationStatusNotDetermined:
            break;
        case kCLAuthorizationStatusDenied:
            _locationDisabled = YES;
            break;
        default:
            break;
    }
}

- (void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region
{
    if (beacons.count > 0 && !_regionExit) {
        for (CLBeacon *beacon in beacons) {
            if ([beacon.proximityUUID.UUIDString isEqualToString:_storeUUID.UUIDString]) {
                NSString *censorType = [NSString stringWithFormat:@"%@", beacon.major];
                if ([censorType intValue] == CENSOR_TYPE_A) {
                    // DO ACTION A
                } else if ([censorType intValue] == CENSOR_TYPE_B) {
                    // DO ACTION B
                }
            }
        }
    }
}

It looks that iPhone4s on iOS 8 has problem with detecting quick region change in background. My test showed that if you loose first region for more than 1 min and enter new region than it is detected immediately. But if you loose region for less than 1 min iPhone 4s won't recognise it and you will have to wait (around 15 min) for full bluetooth scan to notice it. I made workaround that I start ranging after losing first region for 60 seconds, if I will enter next beacon in 60 seconds ranging will detect it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM