iBeacon Tips: 正しいビーコン監視方法

iBeacon 関連の情報をGoogleなどで検索すると、特に日本語ブログなどで示されているiBeaconのCentral(監視側)プログラムでの開始手順が不十分になっています。

そのせいで、ビーコンを試そうとしてうまくいかずに失敗されている方もいらっしゃるかもしれません。

たとえば、検索上位に出てくる、以下のクラスメソッドさんの以下のブログには不十分な手順が記載されています(2013年11月26日現在)。

上記ブログの例では、リージョンに入ったことをトリガにしてビーコンからの通知の受け取りを開始していますが、それではアプリの起動時にすでにリージョン内にいる場合に正常動作しません。

以下に、正しいビーコン監視の開始手順を示します。

例で参照しているプロパティは以下のように定義しています。

@interface ViewController () <CLLocationManagerDelegate>

@property (nonatomic) CLLocationManager *locationManager;
@property (nonatomic) NSUUID *proximityUUID;
@property (nonatomic) CLBeaconRegion *beaconRegion;

@end

viewDidLoad ではCLLocationManagerにビーコン監視の開始を要求しています。定数定義はご自身で適切なものにしてください(UUIDなどは自分で作る必要があります)。

- (void)viewDidLoad
{
    [super viewDidLoad];

    if ([CLLocationManager isMonitoringAvailableForClass:[CLBeaconRegion class]]) {
        self.locationManager = [CLLocationManager new];
        self.locationManager.delegate = self;

        self.proximityUUID = [[NSUUID alloc] initWithUUIDString:SERVICE_UUID];

        self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:self.proximityUUID
                                                               identifier:SERVICE_IDENTIFER];
        [self.locationManager startMonitoringForRegion:self.beaconRegion];
    }
}

ここまでは特に変わったことはありません。

次の、モニタリング開始が正常に始まった時に呼ばれるdelegateメソッドが重要です。

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

ここでiOS7から追加された”CLLocationManager requestStateForRegion:”を呼び出し、現在自分が、iBeacon監視でどういう状態にいるかを知らせてくれるように要求します。

これによって、次のdelegateメソッドが呼ばれます。

- (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region
{
    switch (state) {
    case CLRegionStateInside: // リージョン内にいる
        if ([region isMemberOfClass:[CLBeaconRegion class]] && [CLLocationManager isRangingAvailable]) {
            [self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
        }
        break;
    case CLRegionStateOutside:
    case CLRegionStateUnknown:
    default:
        break;
    }
}

CLRegionStateInside が渡ってきていれば、すでになんらかのiBeaconのリージョン内にいるので、iOS7から追加された”CLLocationManager startRangingBeaconsInRegion:”を呼び、通知の受け取りを開始します。

あとは、リージョンの境界を越えて入った時にも同じく通知を開始するようにします。

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

以上です。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です