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
開発体験を左右するライブラリの API 設計 - GraphQL スキーマ構築ライブラリから考える #tskaigi
izumin5210
2
1.9k
izumin5210のプロポーザルのネタ探し #tskaigi_msup
izumin5210
2
910
AI Agent の開発と運用を支える Durable Execution #AgentsInProd
izumin5210
8
2.9k
AI Agent Tool のためのバックエンドアーキテクチャを考える #encraft
izumin5210
6
2.2k
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.7k
Web フロントエンドエンジニアに開かれる AI Agent プロダクト開発 - Vercel AI SDK を観察して AI Agent と仲良くなろう! #FEC余熱NIGHT
izumin5210
3
1.3k
TypeScript を活かしてデザインシステム MCP を作る / #tskaigi_after_night
izumin5210
5
940
Other Decks in Technology
See All in Technology
しくみを学んで使いこなそう GitHub Copilot app
torumakabe
2
280
ヘルスケア領域における AI 活用と その安全性担保のための取り組み (Leveraging AI in Healthcare and Our Efforts to Ensure Its Safety) - Google I/O Extended Tokyo 2026, July 11, 2026
zettaittenani
0
420
AI時代の開発生産性は、個人技からチーム設計へ
moongift
PRO
4
2.3k
誤解だらけの開発生産性 / Myths and Misconceptions about Developer Productivity
i35_267
2
780
Compose 新機能総まとめ / What's New in Jetpack Compose
yanzm
0
310
“それは自分の仕事じゃない"を越えて行け
yuukiyo
1
460
AICoEでAIネイティブ組織への進化
yukiogawa
0
190
壊して学ぶAWS CDK: そのcdk deployで消えるもの、残るもの
k_adachi_01
1
360
「ちゃんとやっている」は独りよがりだった ― 不安に寄り添うインシデント対応へ / Towards incident response that addresses anxieties
chmikata
1
5.8k
第67回コンピュータビジョン勉強会CVPR2026読会前編
tsukamotokenji
0
140
「早く出す」より「事業に効く」 ── 顧客の業務サイクルから逆算するAI時代の二重ループ開発と「変化の設計者」 / devsumi2026
rakus_dev
1
350
ガバナンスの「ちょうどいい落とし所」を探れ!開発スピードを妨げない運用判断の勘所 / SRE NEXT 2026
genda
1
230
Featured
See All Featured
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
The Cost Of JavaScript in 2023
addyosmani
55
10k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
2.9k
How to build a perfect <img>
jonoalderson
1
5.8k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.5k
Money Talks: Using Revenue to Get Sh*t Done
nikkihalliwell
0
380
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
1
230
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
870
The Curious Case for Waylosing
cassininazir
1
430
How to build an LLM SEO readiness audit: a practical framework
nmsamuel
1
800
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
200
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
410
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