android: ViewModel をやらねばならぬ
2024/10/18
Android で BLE機器を操作するアプリを作ろうとしている。
どういう操作とかもなにもなく、取りあえず作ってみよう、である。
- Peripheral のスキャン
- どれかを選択して connect
- (Notify や Indicate を受け取る設定)
- Characteristic に write なり read なりの操作
大ざっぱにはこういうところであろう。
まだ Android で画面の切替をやっていないので、手順1と2 くらいを実装したい。
いくつか・・・いくつも問題がある。
permission 画面
昔は、Activity
の中などに実装していたが、今は onCreate()
などで composable 関数を呼び出した後は composable の方だけで処理が進みそうな気配がしている。
たぶん、composer 関数は Activity
とは直接関係がないのでメソッドを呼び出したりはできない。
インスタンスを渡せばできるだろうけど、あまりよろしくない気がする。
今の実装では、onCreate()
で BLEアクセスのための位置情報 permission 確認をおこなっている。
もし permission がなければ OS が持ついつもの許可を求めるダイアログが表示される。
許可があれば setContent {}
で composable 画面が表示される。
permission がないと setContent {}
が呼ばれないので、ダイアログで許可しても白い画面のままになっている。
これは return
しなければよいだけだが、そもそも Activity
の方で permission 画面を出してもらうというのは中途半端に思う。
また、今回はアプリ起動時に許可を求めたので onCreate()
で呼び出せたが、許可が必要になったときにダイアログを出したい場合もあろう。
そうしたいなら composable 側から Activity
の実装を呼ぶの?ということになる。
なんか、あまりよいとは思えない(気がする)。
検索するといろいろ出てくるので、composable だけでなんとかなりそうだ。
-
How to Request Permissions in Jetpack Compose: A Step-by-Step Guide - by Rafael Meneghelo - Medium
- ライブラリ “com.google.accompanist:accompanist-permissions” を使えるようにする
AndroidManifest.xml
に<uses-permission>
を書く- 実装は
rememberPermissionState()
を使う
rememberPermissionState
ではなくrememberLauncherForActivityResult()
を使う例もあったが、前者の方が簡単そうだった。
Android の Jetpack ページには「こうしよう」みたいなページがなかったし、Accompanist にも experimental っぽいことが書かれていた(v0.36.0)。
まあ、material3 の Scaffold
API にもそういうのがあったし、永遠のベータ版って感じでこの API を使っていいんじゃなかろうか。
BLEスキャンした一覧を LazyColumn に追加する
BLEスキャン自体はいまのところできている。
Log
で出力させるだけなので、これを LazyColumn
に追加すれば良いだけだ。
と文字で書くのは簡単なのだが、どうやったらよいものやら。
BLEスキャンする部分については暫定的に BleScan に押し込んでいる。
見つかったデバイスは Log.d で出力しているのだが、これをどうにかしないといけない。
BleScan
で List
を作って、その List
を LazyColumn
に渡すのが良いか、
それとも見つかったデバイス情報を次々と上側にコールバックして、データの加工方法は上位層に任せるか。
どっちもどっちな気はするが、アプリアーキテクチャガイドでは「UI elements は State holders のデータを表示するのに専念すべし」だったと思う。
そして State holders は表示するデータを保持したり作ったりする役割。
ビジネスロジックは Data Layer がまかなう。
そういう観点で行くと BleScan
は「スキャンしたデバイスの情報を提供する」ので Data sources になるはず。
その 1段上の Repositories はビジネスロジックを含んでいて、UI Layer は Data sources を直接参照せず Repositories を介するようにするべし。
そういうのがガイドラインだそうだ。
画面のレイアウトは今で何とかなっているとして、次の目標は ViewModel
を作ってダミーデータを表示するところか。
先は長い。