hiro99ma blog

何か技術的なこと

android: ViewModel をやらねばならぬ

2024/10/18

Android で BLE機器を操作するアプリを作ろうとしている。
どういう操作とかもなにもなく、取りあえず作ってみよう、である。

  1. Peripheral のスキャン
  2. どれかを選択して connect
  3. (Notify や Indicate を受け取る設定)
  4. 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 だけでなんとかなりそうだ。

rememberPermissionStateではなくrememberLauncherForActivityResult()を使う例もあったが、前者の方が簡単そうだった。
Android の Jetpack ページには「こうしよう」みたいなページがなかったし、Accompanist にも experimental っぽいことが書かれていた(v0.36.0)。
まあ、material3 の Scaffold API にもそういうのがあったし、永遠のベータ版って感じでこの API を使っていいんじゃなかろうか。

BLEスキャンした一覧を LazyColumn に追加する

BLEスキャン自体はいまのところできている。
Logで出力させるだけなので、これを LazyColumn に追加すれば良いだけだ。

と文字で書くのは簡単なのだが、どうやったらよいものやら。

BLEスキャンする部分については暫定的に BleScan に押し込んでいる。
見つかったデバイスは Log.d で出力しているのだが、これをどうにかしないといけない。

BleScanList を作って、その ListLazyColumn に渡すのが良いか、 それとも見つかったデバイス情報を次々と上側にコールバックして、データの加工方法は上位層に任せるか。
どっちもどっちな気はするが、アプリアーキテクチャガイドでは「UI elements は State holders のデータを表示するのに専念すべし」だったと思う。 そして State holders は表示するデータを保持したり作ったりする役割。
ビジネスロジックは Data Layer がまかなう。

そういう観点で行くと BleScan は「スキャンしたデバイスの情報を提供する」ので Data sources になるはず。
その 1段上の Repositories はビジネスロジックを含んでいて、UI Layer は Data sources を直接参照せず Repositories を介するようにするべし。
そういうのがガイドラインだそうだ。

画面のレイアウトは今で何とかなっているとして、次の目標は ViewModel を作ってダミーデータを表示するところか。
先は長い。

< Top page