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
250
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
AndroidデバイスにFTPサーバを建立する
e10dokup
0
660
Gradleの実行環境設定を見直す
e10dokup
0
1.2k
Firebase App Distributionのテストアプリ配信を試しやすくする
e10dokup
0
670
アプリに署名する 〜GitHub ActionsでのCIも見据えて〜
e10dokup
0
1.2k
Profileable buildでより正確なパフォーマンスを掴む
e10dokup
0
750
[DroidKaigi 2021] メディアアクセス古今東西 / Now and Future of Media Access
e10dokup
0
3.8k
今更「dp」を考える / Let's think about "dp" now
e10dokup
0
5.8k
1から学ぶAndroidアプリデバッグ - アプリの動作を追いかけよう / Learn Android application debugging from the scratch - track apps' behaviors
e10dokup
10
3.3k
Guide to background processingを読んでみる / Reading "Guide to background processing"
e10dokup
0
270
Featured
See All Featured
Rebuilding a faster, lazier Slack
samanthasiow
84
9.3k
Principles of Awesome APIs and How to Build Them.
keavy
127
17k
Site-Speed That Sticks
csswizardry
13
960
[RailsConf 2023] Rails as a piece of cake
palkan
57
6.1k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
231
22k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
359
30k
Producing Creativity
orderedlist
PRO
348
40k
Balancing Empowerment & Direction
lara
5
750
Fashionably flexible responsive web design (full day workshop)
malarkey
407
66k
Navigating Team Friction
lara
190
15k
Statistics for Hackers
jakevdp
799
220k
Rails Girls Zürich Keynote
gr2m
95
14k
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 の発信もできる いわゆる 「すれ違い」 アプリみたいなものはパパっとできる