iBeaconを使ってみよう! 気軽に使える近距離無線通信
underscore Inc.!諏訪 悠紀
!
プロフィール
• underscore Inc.(classmethodの子会社)!
• iOS / Android アプリの企画 & 設計 & デザイン & 開発 & リリース & プロモ & 運用 & 保守!
• Objective-C, Java, Ruby, ...
iBeaconアプリをみんなで作ろう!
• iBeaconは注目されているが、上手く活用しているアプリが少ない!
• 機能はシンプルだが、うまく使うにはちょっとコツがいる(かも)
iBeaconを上手く使って!楽しいアプリを作ろう!
そもそも… iBeaconアプリを作るためには
• Beaconを検知するアプリ!
• Beaconとなる端末が必要
この2つのアプリの!作りかたを解説します
Estimote iPhone Mac
アジェンダ
iBeaconアプリの作りかた!• 領域観測の手順!• 距離測定の手順!
Beaconアプリの作りかた!
ハマりどころ!
まとめ
1
2
3
4
iBeaconアプリの 作りかた
1
iBeaconの機能① 領域観測
Beaconの領域内(Region)への出入りを監視する
!
B
iBeaconの機能② 距離観測 (Ranging)
各Beaconとの距離を約1秒おきに監視する
A
遠 近
領域観測と距離観測の違い距離観測の対象
Beacon
Beacon Beacon
領域観測の対象
Region
それぞれが全く別な機能であると認識しておく
実装する前に…
• Xcode 5!
• iOS SDK 7!
• CoreLocation.framework
領域観測してみるif ([CLLocationManager isMonitoringAvailableForClass:[CLBeaconRegion class]]) { ! // CLLocationManagerの生成とデリゲートの設定 self.manager = [CLLocationManager new]; self.manager.delegate = self; ! // 生成したUUIDからNSUUIDを作成 NSString *uuid = @"41282F26-524C-4F16-9E95-C06D90AF942A"; self.proximityUUID = [[NSUUID alloc] initWithUUIDString:uuid]; ! // CLBeaconRegionを作成 self.region = [[CLBeaconRegion alloc] initWithProximityUUID:self.proximityUUID identifier:@"jp.classmethod.testregion"]; ! // iBeaconによる領域観測を開始 [self.manager startMonitoringForRegion:self.region]; }
領域観測してみるif ([CLLocationManager isMonitoringAvailableForClass:[CLBeaconRegion class]]) { ! // CLLocationManagerの生成とデリゲートの設定 self.manager = [CLLocationManager new]; self.manager.delegate = self; ! // 生成したUUIDからNSUUIDを作成 NSString *uuid = @"41282F26-524C-4F16-9E95-C06D90AF942A"; self.proximityUUID = [[NSUUID alloc] initWithUUIDString:uuid]; ! // CLBeaconRegionを作成 self.region = [[CLBeaconRegion alloc] initWithProximityUUID:self.proximityUUID identifier:@"jp.classmethod.testregion"]; ! // iBeaconによる領域観測を開始 [self.manager startMonitoringForRegion:self.region]; }
iBeaconに対応しているか判定する
領域観測してみるif ([CLLocationManager isMonitoringAvailableForClass:[CLBeaconRegion class]]) { ! // CLLocationManagerの生成とデリゲートの設定 self.manager = [CLLocationManager new]; self.manager.delegate = self; ! // 生成したUUIDからNSUUIDを作成 NSString *uuid = @"41282F26-524C-4F16-9E95-C06D90AF942A"; self.proximityUUID = [[NSUUID alloc] initWithUUIDString:uuid]; ! // CLBeaconRegionを作成 self.region = [[CLBeaconRegion alloc] initWithProximityUUID:self.proximityUUID identifier:@"jp.classmethod.testregion"]; ! // iBeaconによる領域観測を開始 [self.manager startMonitoringForRegion:self.region]; }
コマンドで生成可能
iBeaconに対応しているか判定する
領域観測してみるif ([CLLocationManager isMonitoringAvailableForClass:[CLBeaconRegion class]]) { ! // CLLocationManagerの生成とデリゲートの設定 self.manager = [CLLocationManager new]; self.manager.delegate = self; ! // 生成したUUIDからNSUUIDを作成 NSString *uuid = @"41282F26-524C-4F16-9E95-C06D90AF942A"; self.proximityUUID = [[NSUUID alloc] initWithUUIDString:uuid]; ! // CLBeaconRegionを作成 self.region = [[CLBeaconRegion alloc] initWithProximityUUID:self.proximityUUID identifier:@"jp.classmethod.testregion"]; ! // iBeaconによる領域観測を開始 [self.manager startMonitoringForRegion:self.region]; }
コマンドで生成可能
アプリでの識別用
iBeaconに対応しているか判定する
領域観測してみる
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region { } !- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region { }
CLLocationManagerDelegateの実装
領域観測してみる
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region { } !- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region { }
Exitは20秒~1分後に通知される!(バグではないので注意!)
CLLocationManagerDelegateの実装
デモ!① 入ったり出たりしたら 音を鳴らしてみる
Exitまで 長いですよね。。
距離測定してみる
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region { [self.manager startRangingBeaconsInRegion:self.region]; }
距離測定してみる
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region { [self.manager startRangingBeaconsInRegion:self.region]; }
領域内に入ったときに!距離測定を開始する場合
距離測定してみる- (void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region { CLBeacon *beacon = beacons.firstObject; switch (beacon.proximity) { case CLProximityUnknown: NSLog(@"CLProximityUnknown"); break; case CLProximityImmediate: NSLog(@"CLProximityImmediate"); break; case CLProximityNear: NSLog(@"CLProximityNear"); break; case CLProximityFar: NSLog(@"CLProximityFar"); break; } }
距離測定してみる- (void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region { CLBeacon *beacon = beacons.firstObject; switch (beacon.proximity) { case CLProximityUnknown: NSLog(@"CLProximityUnknown"); break; case CLProximityImmediate: NSLog(@"CLProximityImmediate"); break; case CLProximityNear: NSLog(@"CLProximityNear"); break; case CLProximityFar: NSLog(@"CLProximityFar"); break; } }
配列で渡されるので!それぞれのBeaconの!距離を判定する
デモ!② Beaconの状態を 監視してみる
Beaconの特定に使えるプロパティ
proximityUUID double Regionの識別値
major NSNumber Beaconの識別値①
minor NSNumber Beaconの識別値②
proximity CLProximity 相対距離
accuracy double 精度
rssi NSInteger 電波強度
Beaconアプリの 作りかた
2
Beaconアプリの機能
A B
UUID = XXXX-...!major = 1!minor = 1
UUID = XXXX-...!major = 1!minor = 2
Beaconアプリの機能
A B
UUID = XXXX-...!major = 1!minor = 1
UUID = XXXX-...!major = 1!minor = 2
16ビット符号なし整数!(0~65,535)
実装する前に…
• Xcode 5!
• iOS SDK 7!
• CoreLocation.framework!
• CoreBluetooth.framework
Beaconになってみる- (void)viewDidLoad { [super viewDidLoad]; ! // 生成したUUIDからNSUUIDを作成 NSString *uuid = @"41282F26-524C-4F16-9E95-C06D90AF942A"; self.proximityUUID = [[NSUUID alloc] initWithUUIDString:uuid]; ! // CBPeripheralManagerを作成 self.peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil options:nil]; // アドバタイズ開始処理 if (self.peripheralManager.state == CBPeripheralManagerStatePoweredOn) { [self startAdvertising]; } }
Beaconになってみる- (void)viewDidLoad { [super viewDidLoad]; ! // 生成したUUIDからNSUUIDを作成 NSString *uuid = @"41282F26-524C-4F16-9E95-C06D90AF942A"; self.proximityUUID = [[NSUUID alloc] initWithUUIDString:uuid]; ! // CBPeripheralManagerを作成 self.peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil options:nil]; // アドバタイズ開始処理 if (self.peripheralManager.state == CBPeripheralManagerStatePoweredOn) { [self startAdvertising]; } }
アドバタイズできる状態か判定する
Beaconになってみる- (void)startAdvertising { // CLBeaconRegionを作成 CLBeaconRegion *beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:self.proximityUUID major:1 minor:2 identifier:@"jp.classmethod.testregion"]; ! // NSDictionaryに変換 NSDictionary *beaconPeripheralData = [beaconRegion peripheralDataWithMeasuredPower:nil]; // アドバタイズ開始 [self.peripheralManager startAdvertising:beaconPeripheralData]; }
Beaconになってみる- (void)startAdvertising { // CLBeaconRegionを作成 CLBeaconRegion *beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:self.proximityUUID major:1 minor:2 identifier:@"jp.classmethod.testregion"]; ! // NSDictionaryに変換 NSDictionary *beaconPeripheralData = [beaconRegion peripheralDataWithMeasuredPower:nil]; // アドバタイズ開始 [self.peripheralManager startAdvertising:beaconPeripheralData]; }
作りたいBeaconを設定する
Beaconになってみる- (void)startAdvertising { // CLBeaconRegionを作成 CLBeaconRegion *beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:self.proximityUUID major:1 minor:2 identifier:@"jp.classmethod.testregion"]; ! // NSDictionaryに変換 NSDictionary *beaconPeripheralData = [beaconRegion peripheralDataWithMeasuredPower:nil]; // アドバタイズ開始 [self.peripheralManager startAdvertising:beaconPeripheralData]; }
作りたいBeaconを設定する
電波強度(rssi値)は!カスタマイズ可能
デモ!③ 1台の端末で
Beaconを切り替える
テスト時に便利! 一家に一台
Beaconアプリ
ハマりどころ
3
ハマりどころ① アプリ起動時の領域観測
アプリ起動時(つまり領域観測開始時)に端末がBeaconの領域内に居るとdidEnterRegion:が呼ばれない!
[self.manager requestStateForRegion:self.region];
ハマりどころ① アプリ起動時の領域観測
- (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region { switch (state) { case CLRegionStateInside: NSLog(@"CLRegionStateInside"); // 領域内に入ったときの処理 break; case CLRegionStateOutside: NSLog(@"CLRegionStateOutside"); // 領域内から出たときの処理 break; case CLRegionStateUnknown: NSLog(@"CLRegionStateUnknown"); break; default: break; } }
ハマりどころ① アプリ起動時の領域観測
1. startMonitoringForRegion:で領域観測を始める!
2. requestStateForRegion:で領域内か判定する!
3.領域内であれば入ったときの処理を実行する!
4.領域外であれば何もしない (Enterまで待機)
いい感じに領域観測する手順
ハマりどころ② Push通知に使いたい場合
• バックグランドでは、領域観測はできるが距離観測はできない!
• startMonitoringForRegion:はバックグランドOK!
• startRangingBeaconsInRegion:はバックグランドNG (実行しても10秒くらいで終わる)
ハマりどころ② Push通知に使いたい場合
1.アプリを起動したら領域観測開始!
2. didEnterRegion:ではRegionに入ったことだけ通知する(特定のBeaconに入った通知に使わない)!
3.アプリが表示されたら距離観測を開始する!
4. didRangeBeacons:で処理を行う
領域観測~距離観測の手順
ハマりどころ③ 最も近いBeaconの判定1. didRangeBeacons:は1秒おきに呼ばれる!
2.取得できたBeaconのうち、一番近いBeaconを判定する!
3.一番近いBeaconをアプリ内で保持しておく!
4.次のdidRangeBeacons:で判定した一番近いBeaconと保持していたBeaconを比較する
ハマりどころ④ アプリ終了時の注意点
• startMonitoringForRegion:を呼んだあと マルチタスクからアプリを終了させるとBeaconの領域内に入っても通知されない!!
• マルチタスクから消す = ”アプリからの通知は不要”というユーザーの行為であると捉える
まとめ
4
まとめ
• iBeaconは手軽!(のはず)!
• 用法・用量を守って正しくお使いください!• Beaconが世の中に出回らないうちは、アプリに組み込みましょう!
• アイデアを広げて楽しく便利なiBeaconアプリを作ってリリースしましょう!
iOSアプリリリース中!おまけ
http://underscore-app.tumblr.com/
iBeaconアプリは
まだ ない…
最後までご清聴いただき 誠にありがとうございました!