Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
BLE AdvertiseはRxJavaで何かが変わるのか
Search
Yoshihiro WADA
October 25, 2017
0
240
BLE AdvertiseはRxJavaで何かが変わるのか
2017/10/25 に開催された potatotips #44 にて発表した資料です。
Yoshihiro WADA
October 25, 2017
Tweet
Share
More Decks by Yoshihiro WADA
See All by Yoshihiro WADA
Gradleの実行環境設定を見直す
e10dokup
0
720
Firebase App Distributionのテストアプリ配信を試しやすくする
e10dokup
0
500
アプリに署名する 〜GitHub ActionsでのCIも見据えて〜
e10dokup
0
1.1k
Profileable buildでより正確なパフォーマンスを掴む
e10dokup
0
680
[DroidKaigi 2021] メディアアクセス古今東西 / Now and Future of Media Access
e10dokup
0
3.2k
今更「dp」を考える / Let's think about "dp" now
e10dokup
0
5.4k
1から学ぶAndroidアプリデバッグ - アプリの動作を追いかけよう / Learn Android application debugging from the scratch - track apps' behaviors
e10dokup
10
3k
Guide to background processingを読んでみる / Reading "Guide to background processing"
e10dokup
0
250
よしなに頑張る画像ロードの話 / image load mettya tsurai
e10dokup
2
470
Featured
See All Featured
Ruby is Unlike a Banana
tanoku
97
11k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
47
2.1k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
229
52k
Why You Should Never Use an ORM
jnunemaker
PRO
54
9.1k
Six Lessons from altMBA
skipperchong
27
3.5k
5 minutes of I Can Smell Your CMS
philhawksworth
202
19k
Designing on Purpose - Digital PM Summit 2013
jponch
115
7k
Side Projects
sachag
452
42k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
232
17k
Visualization
eitanlees
145
15k
Code Reviewing Like a Champion
maltzj
520
39k
Build your cross-platform service in a week with App Engine
jlugia
229
18k
Transcript
BLE Advertiseは RxJavaで 何かが変わるのか Yoshihiro Wada a.k.a. @e10dokup 2017/10/25 @
potatotips #44
1 Yoshihiro Wada CyberAgent, Inc. / Adtech Studio (新卒)
@e10dokup
1 Yoshihiro Wada CyberAgent, Inc. / Adtech Studio (新卒)
@e10dokup
2 今日の話題 BLE ってご存知ですか
3 BLE とは BLE (Bluetooth Low Energy) Bluetooth 4.0 の規格の一部。
超低電力でボタン電池で最大 1 年くらい駆動可能。
4 そのなかでも BLE Advertise 未接続の BLE デバイス (ペリフェラル) が スマホ等の接続可能なデバイス
(セントラル) に対し 自身の存在を伝えるためにパケットの発信をする機能 BLE デバイス ワタシハココヨー
5 BLE Advertise BLE Advertise 時に最大 31byte のパケットを送信できる Advertising Packet
この中に規格に合わせて Service UUID 等の情報を埋めていく iBeacon や EddyStone は Advertising Packet の規格
6 BLE Advertise を Android で受け取る BluetoothLeScanner クラスを使う private val
scanner: BluetoothLeScanner private var scanCallback: ScanCallback? = null init { // Kotlinならrunとか使ってこんな風に書けそう scanner = context.run { val manager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager return@run manager.adapter.bluetoothLeScanner } }
7 BLE Advertise を Android で受け取る Scan に対してオプションが設定できる ScanFilter :
スキャン対象を Advertising Packet の中身で フィルタリングする ScanSetting : スキャン間隔や検出個数、 遅延スキャンや スキャン時の callback をどうトリガするなどを設定する startScan(ScanCallack, ScanFilter, ScanSetting) で Scan 開始 stopScan(ScanCallack) で Scan 停止
7 BLE Advertise を Android で受け取る Scan に対してオプションが設定できる ScanFilter :
スキャン対象を Advertising Packet の中身で フィルタリングする ScanSetting : スキャン間隔や検出個数、 遅延スキャンや スキャン時の callback をどうトリガするなどを設定する startScan(ScanCallack, ScanFilter, ScanSetting) で Scan 開始 stopScan(ScanCallack) で Scan 停止
8 ScanCallback onScanResult(int callbackType, ScanResult result) 一台の BLE Advertise を
Scan できた際に呼ばれる ScanFilter を設定していればそれにあったものが呼ばれる onScanFailed(int errorCode) BLE Advertise の Scan を実行できなかった際に呼ばれる すでに Scan を開始しているとか onBatchScanResults(List<ScanResult> results) 遅延 Scan を実行している際、 その遅延の間に Scan できた デバイスのリストが通知される
9 BLE Beacon デバイスで稀によくあること iBeacon の Major/Minor で Beacon の位置を定義してみたり
EddyStone で URL を伝えるようにしてみたり Advertising Packet で何かしら伝えようとしてくる 独自規格でセンサの状態をパケットに設定してきたり
9 BLE Beacon デバイスで稀によくあること iBeacon の Major/Minor で Beacon の位置を定義してみたり
EddyStone で URL を伝えるようにしてみたり Advertising Packet で何かしら伝えようとしてくる 独自規格でセンサの状態をパケットに設定してきたり いい感じに受け取りたい
10 RxJava を使ってみる filter を使って重複回避や本当に必要な分だけ取得したり map を使って Advertising Packet から欲しいデータを得たり
Scan 中は拾えた BLE デバイスがひたすら通知される Observable に扱えれば得られたデータを Web API に流したり とかできそう Observable に扱えるはず
11 実際に実装してみた 取得された Advertise から iBeacon とわかるものをフィルタ フィルタされた Advertise から
iBeacon の Major/Minor、 DeviceName だけを取り出して通知 呼び出し元に 「Scan した iBeacon のデータのみ」 を通知したい Observable.create で Scan 開始から callback までを包む Scan 停止時に disposable を破棄する
Scan 開始を Observable.create で包む // 単純にObservableを返すメソッドに変更 fun start(): Observable<ScanResult> {
return Observable.create { subscriber -> scanCallback = object: ScanCallback() { override fun onScanFailed(errorCode: Int) { subscriber.onError(Throwable(ERROR_MESSAGE)) } override fun onScanResult(callbackType: Int, result: ScanResult?) { super.onScanResult(callbackType, result) result ?: return subscriber.onNext(result) } // 他は省略 } scanner.startScan(scanCallback) } }
iBeacon とわかるものをフィルタ fun check(result: ScanResult): Boolean { // 取得したScan結果からAdvertising Packetを取得
val packet = result.scanRecord.bytes // iBeacon固定値の4byte目の0x02、5byte目の0x15があればtrue return packet[4] == 0x02.toByte() && packet[5] == 0x15.toByte() } scanDisposable = detector.start() .filter { check(it) } .map { transform(it) } .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ // onNext Log.d("MainActivity", String(it.major)) }, { // onError Log.d("MainActivity", it.message) })
必要なデータだけを取得 fun transform(result: ScanResult): IBeaconValue { val name = result.device.name
// デバイス名を取得 val packet = result.scanRecord.bytes val major = byteArrayOf(packet[22], packet[23]) val minor = byteArrayOf(packet[24], packet[25]) return IBeaconValue(name, major, minor) } scanDisposable = detector.start() .filter { check(it) } .map { transform(it) } .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ // onNext Log.d("MainActivity", String(it.major)) }, { // onError Log.d("MainActivity", it.message) })
Scan 開始と終了 // Scan開始 fun startScan() { scanDisposable = scanner.start()
.filter { check(it) } .map { transform(it) } .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ // onNext Log.d("MainActivity", String(it.major)) }, { // onError Log.d("MainActivity", it.message) }) } // Scan終了 fun stopScan() { scanner.stop() // スキャン自体の終了 scanDisposable?.dispose() // 明示的にDisposeさせる }
16 まとめ Scan 自体は Callback 地獄と言う訳ではないので嬉しさは…? おそらく RxJava で書けて嬉しいのは接続した後の処理から BLE
Advertise Scan は RxJava でそれっぽく書ける気がする BLE Advertise だけなら闇はほぼないのでお気軽に試せる ただ iBeacon の発信機は微妙に高い (製品だと 4000 円くらい) Android 5.0 以降なら Advertise の発信もできる いわゆる 「すれ違い」 アプリみたいなものはパパっとできる