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
つらくない(?) Bluetooth Low Energy on Android / TSUR...
Search
izumin5210
September 07, 2015
Technology
3k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
つらくない(?) Bluetooth Low Energy on Android / TSURAI BLE on Android
kyobashi.dex #1 発表資料
http://kyobashi-android.connpass.com/event/18583/
izumin5210
September 07, 2015
More Decks by izumin5210
See All by izumin5210
in-process GraphQL のすすめ #ginzajs
izumin5210
4
1.4k
開発体験を左右するライブラリの API 設計 - GraphQL スキーマ構築ライブラリから考える #tskaigi
izumin5210
2
2k
izumin5210のプロポーザルのネタ探し #tskaigi_msup
izumin5210
2
1k
AI Agent の開発と運用を支える Durable Execution #AgentsInProd
izumin5210
8
3k
AI Agent Tool のためのバックエンドアーキテクチャを考える #encraft
izumin5210
6
2.3k
Building AI Agents with TypeScript #TSKaigiHokuriku
izumin5210
6
1.8k
Web エンジニアが JavaScript で AI Agent を作る / JSConf JP 2025 sponsor session
izumin5210
4
3.5k
AI Coding Meetup #3 - 導入セッション / ai-coding-meetup-3
izumin5210
0
3.8k
Web フロントエンドエンジニアに開かれる AI Agent プロダクト開発 - Vercel AI SDK を観察して AI Agent と仲良くなろう! #FEC余熱NIGHT
izumin5210
3
1.3k
Other Decks in Technology
See All in Technology
モノリス Rails でも日中に rails db:migrate を走らせたい! / Daytime rails db:migrate on Monolithic Rails!
euglena1215
4
640
Eight Engineering Unit 紹介資料
sansan33
PRO
3
8.2k
コネクションをピン留めさせずに SELECTクエリのタイムアウトを設定した話
codmoninc
0
140
FORENSIA: ローカルLLMフォレンジックハーネス
sumeshi
2
420
老害フォレンジッカーはAI羊の夢を見るか?
tadmaddad
0
350
AIコーディングの次。コードレビューと理解負荷を解消して組織の開発生産性を高める
moongift
PRO
2
2.7k
関東Kaggler会発表資料
takoi
1
260
PLATEAU で バーチャル花火大会
tatsuya1970
0
170
FPGAが実現する遠方宇宙の高空間分解能天体撮影 -大型地上望遠鏡の視力を補正する「補償光学」とは?-
komei_mt
0
490
ブラウザ研修 2026
recruitengineers
PRO
7
1.2k
Breaking the Seal: Static Deobfuscation of Compiled V8 JavaScript Bytecode Malware
hshrzd
0
860
社内の7割が使うデータ基盤を、 データチーム2人で回すためにやったこと
koh_yoshi
4
1.5k
Featured
See All Featured
Intergalactic Javascript Robots from Outer Space
tanoku
273
27k
Exploring anti-patterns in Rails
aemeredith
3
470
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
A Guide to Academic Writing Using Generative AI - A Workshop
ks91
PRO
1
370
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.2k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
Groundhog Day: Seeking Process in Gaming for Health
codingconduct
0
280
Product Roadmaps are Hard
iamctodd
55
12k
Utilizing Notion as your number one productivity tool
mfonobong
4
550
KATA
mclloyd
PRO
35
15k
Six Lessons from altMBA
skipperchong
29
4.4k
How Software Deployment tools have changed in the past 20 years
geshan
1
34k
Transcript
つらくない(?) Bluetooth Low Energy Masayuki IZUMI @izumin5210 Masayuki IZUMI @izumin5210
Rekimoto Lab. at the University of Tokyo (2008-2015: Akashi-NCT)
Enginner at Wantedly, Inc. (2014.9-2015.2: Dmetlabel, Inc.)
Ruby JavaScript Android Design pry(main) > izumin.skill_ratio
Bluetooth Low Energy
Android 4.3 (API Level 18) introduces built-in platform support for
Bluetooth Low Energy in the central role and provides APIs that apps can use to discover devices, query for services, and read/write characteristics. - Bluetooth Low Energy | Android Developers
Q. BLE つらくないですか
Q. BLE つらくないですか A. つらいです
BluetoothGatt Bluetooth LE の周辺機器は、サーバとして、センサの値、動作設定 値、内部状態などを公開しています。Bluetooth LE は、ある機能を サービスという単位にまとめます。1 つのサービスは複数のキャラ クタリスティクスを持ちます。例えばエアコンであれば、室内温度
というサービスを作り、そのなかに気温センサの値というキャラク タリスティクスをもたせる設計をしたりします。 - BLE の通信仕様 - Reinforce-Lab.'s Blog* * http://reinforce-lab.github.io/blog/2013/08/13/blebook-ch2-ble-spec/
BluetootGatt GATT (Generic Attribute Profile)
BluetootGatt GATT (Generic Attribute Profile) あらゆる BLE 端末は
GATT に基いて データの送受信を行う
BluetootGatt GATT (Generic Attribute Profile) あらゆる BLE 端末は
GATT に基いて データの送受信を行う Android では BluetoothGatt クラスを利用する
BluetootGatt GATT (Generic Attribute Profile) あらゆる BLE 端末は
GATT に基いて データの送受信を行う Android では BluetoothGatt クラスを利用する ↑ こいつが闇
BLE つらい問題 ちょっと触ってみた結果、どうにも悲しいことに 「1. 安定性がイケてない」 「2. SDK サンプルがイケてない」 「3. API
仕様がイケてない」 という三重苦です。 - Android の BLE で Characteristics の Read/Write サンプルを作ってみた - ReDo** ** http://greety.sakura.ne.jp/redo/2013/11/androidblecharacteristicsreadwrite.html
ここから,このつらい BLE まわりを なんとかマシに出来ないか試行錯誤していきます
BLE つらい問題 ちょっと触ってみた結果、どうにも悲しいことに 「1. 安定性がイケてない」 「2. SDK サンプルがイケてない」 「3. API
仕様がイケてない」 という三重苦です。 - Android の BLE で Characteristics の Read/Write サンプルを作ってみた - ReDo** ** http://greety.sakura.ne.jp/redo/2013/11/androidblecharacteristicsreadwrite.html
どうしようもねえ!!!
イケてない API すべての操作は非同期・コールバックベース
BluetoothGattCallback onConnectionStateChange(BluetoothGatt gatt, int status, int newState) onServicesDiscovered(BluetoothGatt gatt, int
status) onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic)
BluetoothGattCallback onConnectionStateChange(BluetoothGatt gatt, int status, int newState) onServicesDiscovered(BluetoothGatt gatt, int
status) onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic)
BluetoothGattCallback 接続処理 BluetoothDevice#connectGatt() → onConnectionStateChange()
BluetoothGattCallback 接続処理 BluetoothDevice#connectGatt() → onConnectionStateChange() Service 探し BluetoothGatt#discoverService()
→ onServiceDiscovered()
BluetoothGattCallback 接続処理 BluetoothDevice#connectGatt() → onConnectionStateChange() Service 探し BluetoothGatt#discoverService()
→ onServiceDiscovered() 書き込み BluetoothGatt#writeCharacteristic() → onCharacteristicWrite()
BluetoothGattCallback 接続処理 BluetoothDevice#connectGatt() → onConnectionStateChange() Service 探し BluetoothGatt#discoverService()
→ onServiceDiscovered() 書き込み BluetoothGatt#writeCharacteristic() → onCharacteristicWrite() 切断処理 BluetoothGatt#disconnect() → onConnectionStateChange()
BluetoothGattCallback 接続処理 BluetoothDevice#connectGatt() → onConnectionStateChange() Service 探し BluetoothGatt#discoverService()
→ onServiceDiscovered() 書き込み BluetoothGatt#writeCharacteristic() → onCharacteristicWrite() 切断処理 BluetoothGatt#disconnect() → onConnectionStateChange()
BluetoothGattCallback 接続処理 BluetoothDevice#connectGatt() → onConnectionStateChange() Service 探し BluetoothGatt#discoverService()
→ onServiceDiscovered() 書き込み BluetoothGatt#writeCharacteristic() → onCharacteristicWrite() 切断処理 BluetoothGatt#disconnect() → onConnectionStateChange() ↓ 切断は disconnect() して, callback を待ってから close()
イケてない API すべての操作は非同期・コールバックベース 登録できる Callback インスタンスは 1 つ
イケてない API すべての操作は非同期・コールバックベース 登録できる Callback インスタンスは 1 つ
ドキュメントにない仕様(disconnect → close とか)
対策①: 状態を意識する private static final int STATE_DISCONNECTED = 0; private
static final int STATE_CONNECTING = 1; private static final int STATE_CONNECTED = 2; 公式サンプル
対策①: 状態を意識する private static final int STATE_DISCONNECTED = 0; private
static final int STATE_CONNECTING = 1; private static final int STATE_CONNECTED = 2; 公式サンプル たりない
対策①: 状態を意識する enum State { DISCONNECTED, CONNECTING, CONNECTED, SERVICE_DISCOVERING, SERVICE_DISCOVERED,
DISCONNECTING }
対策①: 状態を意識する enum State { DISCONNECTED, CONNECTING, CONNECTED, SERVICE_DISCOVERING, SERVICE_DISCOVERED,
DISCONNECTING } ※ READING / WRITING 等も必要かもしれない
対策②: Callback のハンドリング どの操作のコールバックかを判断するには, 引数に入ってるインスタンス見るしかない 普通にやると Callback Hell
不可避
対策②: e.g. Enum でハンドリング @Override public onCharacteristicWrite() { CharacteristicHandler.valueOf(characteristic.getUuid()) .handle(characteristic);
} enum CharacteristicHandler { DIGITAL_WRITE(/* ... */), DIGITAL_READ(/* ... */) UNKNOWN(null); public static CharacteristicHandler valueOf(UUID uuid) { /* ... */ } public UUID getUUID() { /* ... */ } public void handle() { /* ... */ } }
対策②: e.g. Enum でハンドリング @Override public onCharacteristicWrite() { CharacteristicHandler.valueOf(characteristic.getUuid()) .handle(characteristic);
} enum CharacteristicHandler { DIGITAL_WRITE(/* ... */), DIGITAL_READ(/* ... */) UNKNOWN(null); public static CharacteristicHandler valueOf(UUID uuid) { /* ... */ } public UUID getUUID() { /* ... */ } public void handle() { /* ... */ } }
対策②: e.g. Enum でハンドリング @Override public onCharacteristicWrite(/* ... */) {
CharacteristicHandler.valueOf(characteristic.getUuid()) .handle(characteristic); } enum CharacteristicHandler { DIGITAL_WRITE(/* ... */), DIGITAL_READ(/* ... */) UNKNOWN(null); public static CharacteristicHandler valueOf(UUID uuid) { /* ... */ } public UUID getUUID() { /* ... */ } public void handle() { /* ... */ } }
対策②: e.g. Enum でハンドリング @Override public onCharacteristicWrite(/* ... */) {
CharacteristicHandler.valueOf(characteristic.getUuid()) .handle(characteristic); } enum CharacteristicHandler { DIGITAL_WRITE(/* ... */), DIGITAL_READ(/* ... */) UNKNOWN(null); public static CharacteristicHandler valueOf(UUID uuid) { /* ... */ } public UUID getUUID() { /* ... */ } public void handle() { /* ... */ } }
対策②: Callback のハンドリング どの操作のコールバックかを判断するには, 引数に入ってるインスタンス見るしかない 普通にやると Callback Hell
不可避 上手く処理を移譲させないとヤバい (数千行のなんちゃら Manager クラスとかと対峙するはめに…)
余談 イイ感じのパターンでラップしちゃうのもある e.g. Rx, Promise, Observer, flux
イイ感じのパターンでラップしちゃうのもある e.g. Rx, Promise, Observer, flux 出回ってる BLE
デバイスの SDK はつらい (ハッカソンとかではそのことを念頭に置いた方がいい) 余談
イイ感じのパターンでラップしちゃうのもある e.g. Rx, Promise, Observer, flux 出回ってる BLE
デバイスの SDK はつらい (ハッカソンとかではそのことを念頭に置いた方がいい) BLE まわり,ユニットテストどうするの? (BluetoothGatt は final なので… ラッパー書くしかない?) 余談
BLE,基本的にはつらいです Conclusion
BLE,基本的にはつらいです 公式はあまり信用出来ない(過激派) Conclusion
BLE,基本的にはつらいです 公式はあまり信用出来ない(過激派) 状態遷移を意識しよう Conclusion
BLE,基本的にはつらいです 公式はあまり信用出来ない(過激派) 状態遷移を意識しよう ガバガバ Callback からどうやって処理を
ハンドリングしていくかが重要 Conclusion
http://konashi.ux-xu.com/ https://github.com/YUKAI/konashi-android-sdk/ https://www.flickr.com/photos/36571434@N03/8524872002