同じパターンで Android もいけるだろう、ということで Android Studio + Kotlin の組み合わせで作ってみます。React Native とか Flutter ならいけそうなので、ここはあえて Kotlin で。
カテゴリ一覧を表示するページを追加して。

豪快に MainActivity を書き変えてくれますが、まあ、初手はそれでもいいです。
カテゴリ一覧の取得には web api で 10.0.2.2:8000/mos/api/categories を使って。
戻り値 JSON の例
{
"items": [
{
"id": 1,
"slug": "special1",
"title": "今月のお薦め",
"description": "今月のお薦め商品を紹介します。",
"image": "",
"sortid": 1,
"display": true,
"created_at": "2025-06-05T11:57:01+09:00",
"updated_at": "2025-06-05T11:57:01+09:00",
"deleted_at": null
},
...
React や Blazor のときと同じようにカテゴリ一覧を web api 呼び出しに変更します。
Android の場合はインターネット接続のためのパーミッションを入れる必要があり、きちんと AndroidManifest.xml に追加してくれます。あと、build.gradle にも必要なライブラリを追加してくれます。

ひとまずカテゴリ一覧の作成が完了

コードは MainActivity から CategoryListScreen を呼び出して、データは CategoryViewModel から拾うようになっていますね。ベタで書くよりは ViewModel を使ったほうが良さそうです。
次はカテゴリ内の商品を表示させます。
カテゴリ一覧のカテゴリをクリックしたときに、カテゴリ内の商品の一覧を表示して。
web api は /products/slug/{category_slug} を使って。
レスポンスの例
{
"items": [
{
"id": 13,
"category_id": 1,
"slug": "hotdog3",
"name": "スパイシーチリドッグ",
"description": "",
"image": "m011",
"price": 470,
"sortid": 13,
"display": true,
"created_at": "2024-06-19T02:49:19+09:00",
"updated_at": "2024-06-19T02:49:19+09:00",
"deleted_at": null
},
...
既に web api ができているので、このサンプルを貼り付ければ ok 。ちなみにエミュレータからはホストのPCに対して 10.0.2.2 で接続が可能です。

MainActivity を書き変えて MosNavigation を呼び出すようにしています。この手のナビゲーション機能は、設計時に使うか使わないかの判断をするのですが(そうしないとコーディングの変更が多くて大変)、Claude Sonnet を使うと後からの大幅な変更もやってくれます。

このあたり、アジャイル的にUIを変更するにしても、React や Flutter であったとしても UI 構造の大幅な変更は避けたいものです。なので、共通レイアウトを作ってみたり、共通のベースクラス(BaseActivityを継承するとか)をやりがちになるのですが、生成AIを使ったときにはそのあたりの手間は惜しみません。オブジェクト指向設計の「共通化」の部分がごっそり抜けてあっても大丈夫です。むしろ継承はしなくていい感じですね。このあたりは、将来的なコード技術の進化もあるでしょうが、あれこれと継承しなくてよいのは人間にも楽です。
商品一覧で、商品を選択したときに商品詳細を表示して。
web api は /products/{id}
戻り値の例
{
"id": 1,
"category_id": 6,
"slug": "burger1",
"name": "モスバーガー",
"description": "",
"image": "m001",
"price": 440,
"sortid": 1,
"display": true,
"created_at": "2024-06-19T02:49:19+09:00",
"updated_at": "2024-06-19T02:49:19+09:00",
"deleted_at": null
}
プロンプトはだんだん手慣れてきて、こんな感じに書くようになります。特にプロンプト技術っぽいのもは入っていません。あまり複雑なこともしないし、step by step で進んでいくので、AI 側にも誤解が少ないのでしょう。というか、曖昧さを排除していけば ok です。
そういう意味では、ペアプロしていてドライバー役で後ろから指示を出している感じですよね。キーボード担当の Claude Sonnet が一生懸命コーディングしている感じ。

商品詳細に表示される画像を切り替えます。
商品詳細の画像データは、
10.0.2.2:8000/images/{画像コード}.jpeg
で取得ができるので、これを切り替えて。

画像が表示されるようになりました、が、間違った画像が表示されています。
というか、絶妙にサンプルデータを突っ込んでいますw

これを修正させます。
カテゴリで「今月のお薦め」を選択したときの商品の数が多すぎます。
実際は
localhost:8000/mos/api/products/slug/special1
{
"items": [
{
"id": 13,
"category_id": 1,
"slug": "hotdog3",
"name": "スパイシーチリドッグ",
"description": "",
"image": "m011",
"price": 470,
"sortid": 13,
"display": true,
"created_at": "2024-06-19T02:49:19+09:00",
"updated_at": "2024-06-19T02:49:19+09:00",
"deleted_at": null
},
{
"id": 15,
"category_id": 1,
"slug": "soiburger2",
"name": "ソイバーガー",
"description": "",
"image": "m013",
"price": 260,
"sortid": 15,
"display": true,
"created_at": "2024-06-19T02:49:19+09:00",
"updated_at": "2024-06-19T02:49:19+09:00",
"deleted_at": null
}
],
"total": 2
}
の2つの商品だけです。
サンプルデータを表示していませんか?
カテゴリスラッグ別の商品データは
/mos/api/products/slug/{slug}
を使って。

endpoint のアドレスが間違っていたので、サンプルデータが表示されてしまったようですね。サーバーに接続できない場合にはエラーが出るのが普通だと思うのですが、ここの Claude Sonnet ではサンプルデータを表示するようになっています。後で、これは修正しましょう。

次はカートの機能を実装してもらいましょう。
続きは昼の後で…
商品詳細で「カートに追加」で、カートに追加する機能を実装して。

「カートに追加」ボタンの機能はあるらしいのですが、カートの中身が見れませんw。仕方がないので、カートの中身を見るページを作って貰いましょう。
チキンナゲットの画像があるはずなのですが、絵文字になっているのでうまく拾えていないようです。これは後でチェック。
右上に「カート」のメニューを作って。

CategoryListScreen.kt や ProductDetailScreen.kt のページにがんがんとトップメニューを追加していきます。最初からいれておけよとか、共通化したらどうか?というのは無しです。これは React で作った時も同じですが、人の場合は共通化しないと手間が掛かったり間違ったりするのですが、AIの場合は間違わないのでがんがん手をいれいきます。いや、実際は間違えるのですが、間違えない振りをして多くのファイルに手を入れていく方法に躊躇がありません。
修正方法を間違えるというのは、たまにビルドが通らなかったり文法エラーを起こしているためです。文法エラーになる頻度はそう多くはないのですが、それなりにあります。そのたびに、ビルドができなかった原因を Claude Sonnet が自らチェックをして直していきます。そのあたり、一発で正しいコードが出て来ないので反復という点でうまくいっているような気がします。そのあたり、反復して少しずつ修正していくという手法が実に人間っぽいです。AIですが。


右上にカートのアイコン、そしてカートのページが実装されました。
「注文する」ボタンを実装して。
web api は POST /mos/api/orders
送信する JSON 形式の例
{
total_price: 0,
total_quantity: 0,
items: [
{
id: 1,
price: 1000,
quantity: 2,
},
{
id: 2,
price: 2000,
quantity: 3,
},
],
}
注文した結果が
{ "order_number": "00000000" }
となるので、この注文番号を表示して。

というわけで、やっとこさ注文画面の作成が完了です。これらを一発で書けるようなプロンプトを作ってもよいのですが、ソフトウェアは同じものを作ることはまずありえないので、ペアプロっぽく少しずつ組み立てるのがコツです。
Next.js や Nuxt.js とは違い、ビルドをして Android エミュレータに転送しないと動作確認ができない分だけ、ちょっと時間がかかります。それでも午前中に始めて、多少間があいて現時点(22時頃)には終わります。間に他の仕事をしていたので、おそらく半日でここまでいけます。

おそらく、手慣れた Android アプリの開発者であれば、似た感じのものを半日で作れると思います。ですが、Copilot + Claude Sonnet の組み合わせだと、まあそれなりのものがこのペースで作れるわけです。果たして新人が作れるかどうかは分かりませんが(おそらく新人だとコードの内容が理解できないので、ハマると大変そうです)、何回か Android アプリを作っている人であれば、同じ形でできるでしょう。コードやファイル構造を眺めると、こんな感じです。
- UI に Jetpack Compose を使う
- ViewModel を使う
- Retrofit を使う
- NavHostController を使う
- データクラスをちまちま作る
という構造になっています。これがベストな方法かよくわからないのですが、現状の Claude Sonnet のベストプラクティスなのだと思います。
サンプルコード
https://github.com/moonmile/mos-ai-sample/tree/master/src/client/mos-kotlin
