ChatGPTと一緒にWear OS版の買い物リストアプリを作った話[Kotlin/Jetpack Compose]

に公開

こんにちは、暑すぎて毎日床とお友達ののふぃです。

以前作った、家庭用買い物リストアプリ「TODO(とど)」。

https://techbookfest.org/product/c6BhWe94Gj60A20s28YQUW?productVariantID=haB35pqkPCH3cKXSrJugrz

ついに、スーパーでスマホをカバンから出すのすら面倒!! と感じてしまったので、
スマートウォッチ用のアプリを開発しました!

元サイトであるTODO(とど)の実際の画面はこんな感じです。

買い物リストが表示されている状態のスクリーンショット
+ボタンを押すと、項目を追加するドロワーが開きます。
項目を追加するドロワーのスクリーンショット
グループを選択することもできます。
グループを選んで項目を追加するドロワーのスクリーンショット

構成はこちらです。

- ホスティング Firebase
- Webサイト構築 Remix
- データ保存 Firestore
- デザイン Tailwind CSS, Flowbite React
- テストツール Vitest,  jsdom, Testing Library
- エディター VSCode
- ソース管理 GitHub

ChatGPTに相談しながら始めてみる

Androidどころかアプリ開発自体も初めてなので、情報収集から。
ということで、今回はChatGPTにイチから聞いて進めました。

対象のスマートウォッチは何を選ぶ?

Swiftを使ってApple Watch向けに作ろうと考えていましたが、その場合は以下のいづれかの方法を選ばなければならず、金銭面と手間から断念しました。

・App Storeに公開する
 →審査がある
・無料Apple ID + Xcodeで自分でインストールする
 →使えるのは自分のデバイスでのみ、7日ごとに署名の更新が必要
・Apple Developer Programを利用する
 →最大100台にインストール可能だが、年額12,800円

ということで(?)、Galaxy Watch(wearOS)向けに開発することにしました。

すでにスマートフォンでTODOを使ってくれている身内がGalaxy Watchを使っているので、一旦はその人向けに開発してみよう!という理由です。

Googleのplayストアに登録しなくても、開発者モードでインストールしてそのまま使えそうです。
(アプリの更新を反映したい場合はその都度インストールが必要ですが、それ以外で署名などはない。)

wearOS向けのツールや言語って何がある?

エディターはAndroid Studio

https://developer.android.com/studio?hl=ja

「Android studio」とはその名の通り、Android端末向け(スマートフォンやスマートウォッチなど幅広く)のアプリ開発ができる開発用の統合開発環境(IDE)です。

Googleが公式に提供しています。

言語はJavaとKotlinのどちらか

https://www.java.com/ja/
https://kotlinlang.org/

Androidアプリの開発といえばKotlinのイメージがあるけど、Javaでも書けるんだ、へえ〜。

と思っていましたが、ChatGPTによると以下の理由でKotlinが圧倒的におすすめらしいです。

・Google公式が推奨
 Android開発の第一言語。今後の新機能はKotlin優先。
・UI構築がシンプル
 Jetpack Composeが使える(Wear OSの推奨UI)
・Null安全などでバグが減る
 型システムが強力
・ドキュメント・チュートリアルが豊富
 Kotlin中心の解説が多い

特に、Firebaseを使いたい場合はKotlin一択らしいです。

今回は、すでにある買い物リストのデータをウォッチでも共有したいので、Firebaseは必須。

ここは提案に従ってKotlinを採用します。

UIは何を使ったらいい?

Wear OS では、UI構築に Jetpack Compose for Wear OS という仕組みが主流になっているそうです。

https://developer.android.com/training/wearables/compose?hl=ja

Jetpack Composeとは、Android向けの宣言的UIフレームワークです。

UI構造をそのままコードとして記述でき、可読性が高いというメリットがあります。

@Composable
fun ButtonSample() {
    // ボタンが押された回数を記録
    var count by remember { mutableStateOf(0) }

    // 画面中央に配置するためのBoxとmodifier
    Box(
        modifier = Modifier.fillMaxSize(),
        contentAlignment = Alignment.Center
    ) {
        Column(horizontalAlignment = Alignment.CenterHorizontally) {
            // ボタン本体
            Button(
                onClick = { count++ },
                modifier = Modifier.padding(16.dp)
            ) {
                Text("クリック!")
            }

            // テキストを表示
            Text("押した回数: $count 回")
        }
    }
}

@Composableアノテーションの意味

@Composable をつけることで、この関数は「ComposeのUIツリーの一部として呼び出せる」ことを示しています。

つまり、UIを構築する関数だよ!とコンパイラに伝えるためのアノテーションです。

次のような関数では @Composable をつけません。

・UIを直接描画しない関数
・計算やデータ処理など、UIとは無関係なロジック
・Composable関数の外側でしか使わない処理(例:ViewModel内のビジネスロジック、リポジトリ、API通信など。)
・Composeツリー外で呼び出される関数(例:main() や onCreate() のようなエントリポイント。)

Stateで変更を監視できる

var count by remember { mutableStateOf(0) }

rememberとmutableStateOfというAPIを利用してcountを初期化しています。

ユーザーの操作などでStateが変更されると、フレームワークがそれを感知して再コンポーズします。

rememberを使うと、再コンポーズを超えて値が保持されます。

modifier(修飾子)でコンポーザブルの装飾や拡張ができる

修飾子を使用すると、次のようなことが可能になります。

・コンポーザブルのサイズ、レイアウト、動作、外観を変更する
・アクセシビリティラベルなどの情報を追加する
・要素をクリック、スクロール、ドラッグ、ズームできるようにするなど、高度なインタラクションを追加する

modifierはKotlinの標準オブジェクトです。

https://developer.android.com/develop/ui/compose/modifiers

ちなみに、Jetpack ComposeはKotlinでのみサポートされており、Javaでは使えません。

サンプルのボタンのようなUIを書くにはKotlinが必須です。

Firebase連携は簡単?

すでにあるリストデータをウォッチでも共有したいので、データの保存はそのままFirestoreを利用します。

Firebaseのプロジェクトに「アプリを追加」することで利用できます。

Kotlin側のFirebase連携はこんな感じでできます。

val db = FirebaseFirestore.getInstance()
val newTodo = Task(
    id = UUID.randomUUID().toString(),
    todo = inputText,
    checked = false,
    date = Timestamp.now(),
    group = ""
)
db.collection("collection-path").add(newTodo)

出来上がりの画面

今回挑戦したスマートウォッチはどうしても画面が小さいので、項目の追加(グループは選択不可)と削除の機能だけをつけています。

出来上がりの画面(エミュレーター)がこちらです。

買い物リストが表示されているスマートウォッチの画面

見た目の点で、項目追加の+ボタンの部分を Buttonではなく TextFieldにしています。

これは、「入力欄にフォーカスを当てると自動で開くウォッチのキーボード上で、入力した文字が表示されない」という実機のみで起きる現象の対処(未解決)でそうしています。

元アプリのように+の丸ボタン(Button)でキーボードを開く場合、「入力欄(TextField)が存在しているが見えない状態」にする必要があります。

しかし、フォーカスの制御やTextFieldのサイズ、透過率などが影響して先の現象が起きている可能性もあるため、単純なTextFieldを採用しています。

ウォッチに内臓されたキーボードアプリ(?)の問題の可能性もあるのですが、色々と見識が浅すぎて解決はしていません。

おわりに

詳細やはじめかたはおいおい文字に起こすとして、今回はその概要だけをまとめました。

最終的な構成はこちらです。

- ホスティング Firebase
- アプリ構築 Kotlin
- UI構築 Jetpack Compose
- データ保存 Firestore
- テスト 未定
- エディター Android Studio
- ソース管理 GitHub

webと違ってツールがまとまっていて数も少ないため、何を採用するかで迷うことはなさそうですね。

とりあえず、wear OS向けにアプリを作る際はAndroid Studioを使ってKotlinとJetpack Composeでやってみるとなんとかなる! ということがわかりました!

ですが、実際にやってみるとこんな感じに色々な問題が発生したので、これから地道にまとめていきたいと思います。

・composeのimport元がたくさんあってどれかわからない
・Firebaseと接続する時の設定がちょっとよくわからない
・Android Studioの使い方がそもそもわからない
・実機でデバックするための接続方法が難しい

chatGPTが話をまとめてくれるので助かったのですが、嘘言ったり話したこと忘れたりするので、こちらが簡潔に情報をまとめたり、読んでほしいドキュメントを指定すると話が早かったです。

もっとコード寄りのAIも使ってみたいですね。

Discussion