Отображать фоновое уведомление, когда CLProximityNear

Я пытаюсь отобразить уведомление, когда мое приложение находится в фоновом режиме, и устройство входит в область iBeacon, и когда их CLProximity находится рядом, уведомление работает, но оно продолжает появляться с интервалом в 1 секунду:

- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region{
    NSLog(@"Entered beacon region");
    [self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
}

- (void) locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region{
    NSLog(@"Left region");
    [self.locationManager stopRangingBeaconsInRegion:self.beaconRegion];
}

- (void) locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region {
    [self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
}
- (void) locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region {
    CLBeacon *beacon = [[CLBeacon alloc] init];
    beacon = [beacons lastObject];
    self.uuidLabel.text = beacon.proximityUUID.UUIDString;

    if(beacon.proximity == CLProximityUnknown) {
        distanceLabel.text = @"Unknown Proximity";
        [self.view setBackgroundColor:[UIColor grayColor]];
    } else if (beacon.proximity == CLProximityImmediate) {
        distanceLabel.text = @"Immediate";
        [self.view setBackgroundColor:[UIColor redColor]];
    } else if (beacon.proximity == CLProximityNear) {
        distanceLabel.text = @"Near";
        [self.view setBackgroundColor:[UIColor orangeColor]];
        UILocalNotification *inRange = [[UILocalNotification alloc] init];
        inRange.alertBody = [NSString stringWithFormat:@"Entered region!"];
        inRange.soundName = UILocalNotificationDefaultSoundName;
        [[UIApplication sharedApplication] presentLocalNotificationNow:inRange];
    } else if (beacon.proximity == CLProximityFar) {
        distanceLabel.text = @"Far";
        [self.view setBackgroundColor:[UIColor blueColor]];

    }
}

Должен ли быть вызов метода после отображения уведомления, чтобы сообщить приложению, что оно было отображено, и не вызывать метод didRangeBeacons до тех пор, пока пользователь не выйдет за пределы диапазона и не вернется снова?


person George McDonnell    schedule 17.01.2014    source источник


Ответы (2)


При ранжировании маяков locationManager:didRangeBeacons:inRegion будет вызываться каждую секунду, как вы определили. Каждый раз параметр beacons будет содержать массив всех видимых маяков.

Ваше приложение должно содержать логику для определения того, виден ли новый маяк или вы уже уведомили пользователя об этом. Я предлагаю вам сохранить массив ранее обнаруженных маяков, и каждый раз, когда вызывается locationManager:didRangeBeacons:inRegion, вы сравниваете свой список с содержимым параметра beacons. Затем вы сможете сказать, были ли найдены какие-либо новые маяки.

person James Frost    schedule 17.01.2014

Несколько уведомлений можно решить следующим образом:

Если вы хотите, чтобы уведомление было отправлено только один раз, просто определите флаг alreadyDisplayed, который устанавливается после отправки уведомления, а затем проверьте его значение перед отправкой.

Как это:

BOOL alreadyDisplayed = NO;

...

- (void) locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region {

  ...

  else if (beacon.proximity == CLProximityNear) {
    distanceLabel.text = @"Near";
    if (!alreadyDisplayed) {
      [self.view setBackgroundColor:[UIColor orangeColor]];
      alreadyDisplayed = YES;
      UILocalNotification *inRange = [[UILocalNotification alloc] init];
      inRange.alertBody = [NSString stringWithFormat:@"Entered region!"];
      inRange.soundName = UILocalNotificationDefaultSoundName;
      [[UIApplication sharedApplication] presentLocalNotificationNow:inRange];
    }
  }

...

}

Но у вас все еще есть вторая проблема:

Если вы хотите сделать это в фоновом режиме, как следует из названия вашего вопроса, это вообще не сработает. Проблема в том, что после того, как iOS обнаружит, что ваш телефон вошел в область iBeacon в фоновом режиме, она позволяет ему работать только в течение пяти секунд, прежде чем перевести его в спящий режим. Поскольку диапазон iBeacon составляет около 50 метров, наиболее вероятным случаем является то, что этот пятисекундный интервал начнется, когда вы окажетесь на краю этого 50-метрового диапазона. Очень маловероятно, что пользователь будет ходить так быстро, что войдет в близость «Близко» в течение 5 секунд, которые у вас есть, прежде чем ваше приложение будет переведено в спящий режим. По этой причине, как правило, невозможно предпринять конкретные действия, основанные на определенной близости, когда вы находитесь в фоновом режиме.

Тем не менее, если вы хотите сделать это на переднем плане, это будет отлично работать, если вы внесете изменения, чтобы уведомления не приходили каждую секунду.

person davidgyoung    schedule 17.01.2014
comment
Так не лучше ли выяснить, когда пользователь пересек границу, а затем выяснить, сколько времени прошло между пересечением региона, чтобы убедиться, что это подходящее время для отображения уведомления? - person George McDonnell; 18.01.2014
comment
Я не уверен, что это помогает. В фоновом режиме ваше приложение будет работать только в течение пяти секунд после пересечения границы. Если пользователю требуется 15 секунд, чтобы подойти к близи, ваше приложение не будет запущено, и вы вообще не сможете представить уведомление. Если вы подождете, пока ваше приложение в следующий раз проснется, будет слишком поздно. К сожалению, это реальное ограничение iBeacons на iOS, и я не верю, что это можно обойти. Чтобы срабатывать на определенном расстоянии, ваше приложение должно быть на переднем плане. - person davidgyoung; 18.01.2014