
ローカルLLMだけでAndroidアプリを開発した ~クラウド級のLLMを個人が持つ新時代に突入~
こんにちはRcatです。
今回は個人的にかなり衝撃を受けています。まさに新時代が来たって感じ。
タイトルに書いてますが"ローカルLLM"がAndroidアプリ作っちゃったんですよね…。クラウドのならもう当たり前の領域ですが、自分のPCだけで出来ちゃったのです…
というわけで、何をやったのか。何を作ったのか紹介していきます。
はじめに
利用規約
情報や作品の活用時は事前に利用規約をご確認ください。
コメントについて
利用規約のガイドラインを確認の上コメントしてください。
則っていないコメントは削除します。
概要
きっかけ
こちらの記事が始まりです。
Qwen3.8-Flash-Nextを導入したのですが、ベンチとして用意した既存のプロジェクトの再実装は難なくクリア。
このアプリはLaguna S2.1で実装したもので、つまり能力が向上したのか正直わかっていませんでした。
次にこちらの記事です。
Pixel11のTensor G6のTPUならGemini nanoが爆速で動くことがわかりました。
しかし、現状専用のAICoreから実行してチャットした場合だけ。単発限定で会話は不可能な感じ。Pixelの基本機能がうまく活用してるかもって程度。
宝の持ち腐れ感が否めない。
そ・こ・で
TPU叩くアプリが作れたら面白んだろうなと思いました。
Qwen3.8 Flash NextってClaude Opus 4.6より上って聞きました。
Claude Opusの4.6とか7の辺りで次元が違うって話を聞いていました。
→あれ、つまりQwen3.8 Flash Nextなら、もしかしてAndroidアプリ丸投げで作れるのでは?
というのがきっかけです。
作成したアプリ - SLMチャットアプリ
Gemini nanoを叩くアプリです。
デバイス実行なのでオフラインでも使えます。
メイン画面
はい、こんな感じです。
つまり開発は成功しました。

モデル選択
AI Coreの方で選べる4種類を選ぶことができます。

チャット機能
チャット画面は簡易的です。
なお、AICoreではできない複数ターンに対応。
最後の質問を見れば、ちゃんと前の発言を考慮していることがわかります。

当たり前かもしれませんが、ちゃんと前の履歴を含んだ状態でAI側に投げないとチャットにはならないんですよね。
翻訳
オフラインでAIとチャットできたところで、「で?」となりかねません。
では「オフラインで翻訳ができます」だったらどうでしょうか。
入力した文章の言語を自動判定して指定言語に翻訳できます。
コピペ完備でそこそこ使いやすい

結果をコピーしてリバース翻訳。
まぁ2回翻訳を繰り返したにしては上出来?意味的には問題ありませんし。

サーバー機能
OpenAI互換APIをホストする機能。
うまくいけば外部からのAPIリクエストをさばける。
これはコンテキストの関係で無理でした。
一応動くのですが、ZooCodeをつないだら「こんにちは!」でも長すぎてエラーになってしまいました。
うーん。スマホエージェント試してみたかったのにな。
ベースとなったGemma4 E4Bは128kコンテキストに耐えるので、モデル的には動くはずなんですけどね。
※ちゃんとエージェントできるとは言っていないw
ローカルLLMでアプリ開発
ここからは実際の開発の経緯や手順を時系列で解説していきます。
Geminiに相談
とりあえず、LinuxでAndroidアプリ作れる?と投げます。
AndroidはLinuxだし作れるはずですが、話の流れを作るための質問ですね。

環境構築の話をしたところで、コンテナだったらどう作るか聞きます。
ローカルLLMはOpenHandsのコンテナ内で動いているので、その中で開発してもらうためです。

教えてもらった方法をコピーしたら終了。
ローカルLLMで環境構築
ここからはローカルです。
いつも通り、プラットフォームはOpenHands。モデルはQwen3.8 Flash Next IQ3 XXSです。
ワークスペースを作り、Geminiの回答をコピペして、環境構築ができるかどうか試してもらいます。

しばらくして完成しました。
どうやらテストアプリもビルドしたようです。

AI CoreのAPIを叩く依頼をする
次に、アプリ内のリンクからSDKの使い方に飛べるのでそれを渡します。
gitリポジトリのようなのでクローンさせてもいいでしょう。


しばらく放置すると、なんと推論できたそうです…。
AICoreじゃなくてギャラリーの方からのリンクだったからだと思うのですが、任意のモデルを持ってきて実行したみたいですね。

勘違いを正す
今回叩くのはAI Coreに依存するモデルなので、任意のモデルではありません。そこの認識をただします。

結果としてGemini nanoにたどり着いたようです(本人も実はアレなんだっけ状態だったw)

ここで初めてGemini nanoの正確な名前が出ます。
それを呼ぶようにしてほしいと依頼をします。

Gemini nano 呼び出しアプリができた
というわけでしばらく待つとなんとアプリができたっぽいですね。

ちょっと寄り道
実はこの時仕事中で、離席時にちらっと見て完了してたら指示だししてたんですねw。これでお仕事中でも開発が進むのです。
家にいないとインストールはできないので、まずはここまでの内容をまとめてもらっておきます。
ついでにOpenAI互換サーバーとか言う狂った機能を追加したのもこのタイミング。

ワイヤレスデバッグを接続
家に帰ったらさっそく実機を接続します。
USBはコンテナから認識できるのかよくわからないので、IPで行けるワイヤレスデバッグにしました。

ペアリング後、デバッグ用のポートを教えればあとは勝手にアプリをインストールして起動、操作して挙動チェックをしてくれます。
まじかぁw

バグつぶし
実機に入れるというか、エミュレータもまだ導入していなかったので、UIがどうなるのか分かっておらず、初回はボタンが画面外にある状態でしたw。
ほかにもいろいろあるので、全部言って直してもらいます。

実機での推論成功
画面レイアウトを主に直したところ、ちゃんと動くものになりました!

モデル選択とチャット履歴を追加
初期はモデルはいい感じに選んでくれる仕様だったらしいのですが、自分で選べるようにしたいのでここで仕様を明示。
また、複数ターン会話への対応もここで明示しました。

しばらく待って実装完了。
だいぶアプリっぽくなってきました。

エミュレータの接続
今更ですがエミュレータがここで登場します。
推論関係は無理でもUIがきちんとできているかどうかを見られれば、初回にあったボタンが画面外というのは実機に入れる前にわかるようになります。

エミュレータは別のDockerコンテナで立ち上げておきます。
イメージ名は下記です。
`budtmo/docker-android:emulator_14.0`
結果がこんな感じ。
アプリを入れた後のスクショを取って共有してくれました。
UIがチェックできるようになったのは大きいです。

正規リポジトリを作成
なんだかんだでここまで「アプリ作れる?」という会話から始まってしまったので、フォルダ内がごちゃごちゃです。
さすがにまずいので、一旦作ったアプリをリモートにプッシュしたのち、別のフォルダにクローンしてもらい正規作業場を作ります。
AGENTS.MDの入ってないので、無法地帯なのもまずい。


再開
作り直したワークスペースで新規会話を作成します。
いきなり指示だしすると迷いそうなので、まずは理解してもらいます。

仕様書の作成とレビュー
やっとそれっぽくなってきましたね!
現状は話の流れで出来たアプリになっているので、一旦仕様書に起こしつつ、そこに対してこれからやりたい機能を盛り込みます。
ここで初めてあのトップ画面が現れるんですね。

出来上がった仕様書のレビューをして、問題点や変更点を指摘します。

実は翻訳機能はだいぶ後出しだったりします。

設計書の確認とGOサイン
仕様書がOKなら設計書を書かせます。
大丈夫そうなら進め方の補足だけしてGOサインを出します。


数時間かかって作業完了。
エミュレータを使ってUIの問題があったことを報告してくれます。
やはり導入して正解でしたね。入れてなかったら、実機に入れてそこで修正かけないといけないところでした。

この後実機をつないでインストールしてもらいました。
アプリアイコンとダークテーマ化
ひとまずここで機能が出そろったので、あとは見た目です。
アプリアイコンをセットしてもらい、ダークテーマにしてもらいます。

この後も細かいやり取りはあるのですが、些事なので省略。
これにてAndroidアプリが完成しました。
まとめ
今回は完全ローカルでAndroidアプリを丸投げ開発しました。
技術界隈ではよく聞くClaudeなら前から余裕だったのでしょうけど、それがとうとうローカルでもできてしまうようになったというのが驚きです。
特に、今まではPythonやnodeのような環境構築が要らない(ライブラリくらい)のような言語を任せていました。
しかし、今回は開発に必要なパッケージやjavaの導入なども完全に丸投げしている点でさらにスコープが多くなっています。
そのうえでアプリはビルドしなければなりません。
よくもまぁこんな作業をローカルLLMがやれるようになったものだと思います。
さすがに重めのモデルなので、大体1タスク1,2時間かかりますが、仕事中に勝手に進めててくれていることを考えれば十分。
それではまたお会いしましょう。
リンク集
感想投稿フォーム
コメントは公開で恥ずかしい!! Rcatだけに送りたい人向け