ANTIGRAVITY LABEN
記事一覧/アプリ開発
アプリ開発/2026-06-26上級

埋め込みエミュレータでは緑なのに、実機で初めて崩れる — AI 生成 Compose アプリに実機差を塞ぐ検証ゲートを置く

AI Studio はテキストから Kotlin/Compose アプリを生成し、埋め込みエミュレータで動かし、USB で実機へ送るところまで一画面でつなぎました。けれどエミュレータで通った画面が、手元の実機で初めて崩れることがあります。個人開発で複数アプリを抱える立場から、生成物に実機差を塞ぐ検証ゲートを据える設計をまとめました。

AI Studio5Antigravity271Jetpack Compose5Android23app-dev40

プレミアム記事

最初に崩れたのは、ある壁紙アプリの設定画面でした。AI Studio に「設定項目をカード型に並べ替えて」と頼み、埋め込みエミュレータで確認したときは、余白も角丸も思ったとおりでした。安心して USB でつないだ実機に送り、そこで初めて、一番下のカードがナビゲーションバーの下に半分隠れているのに気づきました。

エミュレータでは緑、実機で赤。この組み合わせがいちばん厄介です。生成も実行も実機転送も一画面でつながったいま、確認の往復は驚くほど速くなりました。けれど速くなったのは「エミュレータでの確認」であって、「実機での確認」ではありません。私自身、最初の数週間はこの差を甘く見ていて、内部テストに配ってからテスターに指摘される、という遠回りを何度かしました。

この記事は、AI Studio や Antigravity が生成した Compose アプリに対して、エミュレータと実機の差を先回りで塞ぐ検証ゲートをどう据えるか、という話です。生成が速くなったぶん、検証だけは意図して遅く、固く保つ。その線引きと実装をまとめます。

なぜエミュレータは通って実機で崩れるのか

実機差は気まぐれに見えて、出どころはおおむね四つに整理できます。先に地図を持っておくと、生成物のどこを疑えばよいかが定まります。

システムインセット — ノッチとナビゲーションバー

ひとつめはシステムインセットです。エミュレータは素のジェスチャーナビゲーションや切り欠きのない画面で動くことが多く、生成されたレイアウトが WindowInsets を無視していても表面化しません。実機にはノッチ、パンチホール、3 ボタンナビ、丸い角があり、ここで初めて要素が隠れます。冒頭のカードが沈んだのも、生成コードが navigationBarsPadding() を当てていなかったためでした。

フォントスケール — 固定 dp の弱点

ふたつめはフォントとスケールです。実機のユーザーは表示サイズやフォントスケールを変えています。エミュレータの初期値(スケール 1.0)でだけ整って見える固定 dp の高さは、fontScale 1.3 の実機でテキストがクリップされます。AI が生成するレイアウトは、見た目を整えるために固定高さを置きがちで、ここが弱点になりやすいところです。

GPU レンダリング — エフェクトの落ち方

みっつめはGPU レンダリングの差です。エミュレータはホストの GPU を使うため、blurgraphicsLayerRenderEffect のようなエフェクトが滑らかに出ます。実機の特定 GPU・特定 OS では同じエフェクトが落ちたり、目に見えるカクつきになったりします。壁紙アプリのようにぼかしを多用すると、この差は無視できません。

ロケールと RTL — 反転で崩れる

よっつめはロケールと右書きです。エミュレータを日本語のまま確認していると、アラビア語などの RTL で要素が反転して崩れる箇所に気づけません。日本語圏向けでも、ストアの審査や海外テスターで RTL は普通に踏みます。

この四系統を頭に置くと、「生成物を実機で確認する」が「四つの観点で実機差を狙い撃ちする」に変わります。漠然と眺めるより、はるかに早く崩れを見つけられます。

観点を、消えないチェックに変える

頭の中の観点は、疲れている夜には抜けます。私は四系統を、消えないチェックとしてコードとプレビューに固定することにしました。生成のたびに人が思い出す前提を捨てる、というのが狙いです。

まず、インセットとフォントスケールは Compose プレビューで先に炙り出します。生成されたコンポーザブルに対し、極端な条件のプレビューを並べておくと、エミュレータを起動する前に崩れが目に入ります。

// 実機差を炙り出す「いじわるプレビュー」を生成物の隣に固定する
// fontScale を上げ、狭い高さに押し込み、RTL を当てる
@Preview(
    name = "Large font + short height",
    fontScale = 1.5f,
    heightDp = 360,
    showBackground = true,
)
@Preview(
    name = "RTL locale",
    locale = "ar",
    showBackground = true,
)
@Composable
private fun SettingsCardStressPreview() {
    AppTheme {
        // 実機のシステムバー領域を擬似的に差し込み、インセット忘れを可視化する
        Box(Modifier.windowInsetsPadding(WindowInsets.systemBars)) {
            SettingsCardList(items = sampleSettingsItems)
        }
    }
}

fontScale = 1.5fheightDp = 360 を当てるだけで、固定 dp 高さに押し込まれたテキストはプレビュー上でクリップされて見えます。locale = "ar" を足せば、左右非対称なパディングがそのまま反転して崩れる箇所が出ます。生成直後に AI へ「このプレビューで崩れているので fontScale に追従するレイアウトへ直して」と返せば、エミュレータを開く前に一周回せます。

インセットの取りこぼしは、レイアウト側で恒久的に塞ぎます。スクロールする一覧なら、コンテンツの最後がナビゲーションバーに隠れないよう、インセットをパディングへ変換しておきます。

// 一覧の末尾がシステムバーに沈まないよう、インセットを contentPadding に流し込む
LazyColumn(
    contentPadding = WindowInsets.systemBars
        .add(WindowInsets(top = 8.dp, bottom = 8.dp))
        .asPaddingValues(),
) {
    items(settingsItems, key = { it.id }) { item ->
        SettingsCard(item)
    }
}

これで冒頭のカードが沈む事故は構造的に起きなくなります。大切なのは、生成物に対してこの修正を「毎回お願いする」のではなく、テンプレート側に持たせて生成の出発点に組み込むことです。AI に任せる範囲を、崩れにくい土台の上に限定するわけです。本番運用に入る前にこの土台を固めておくことを強くお勧めします。落とし穴は、生成のたびに人が同じ注意点を思い出せると過信することにあります。

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
エミュレータと実機で挙動が割れる箇所を、フォント・インセット・GPU・ロケールの4系統に分けて先回りする観点
Android CLI と Compose プレビューのスナップショットを使い、実機差を CI のゲートに落とし込む実装手順
生成と検証を分離し、AI に直させてよい失敗と人が判断する失敗を切り分ける運用契約
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Antigravity Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

アプリ開発2026-06-26
生成も配信も任せても、署名鍵だけは渡さない — AI 主導の配布パイプラインで鍵の管理と引き継ぎを設計する
AI Studio や Antigravity が生成から内部テスト配信までを肩代わりする時代でも、アプリの署名鍵だけは別格です。鍵を失えば、そのアプリは二度と更新できません。個人開発で複数アプリを長く運用してきた立場から、アップロード鍵とアプリ署名鍵の分離、鍵の保管、そして万一の引き継ぎまでを設計としてまとめました。
アプリ開発2026-06-24
生成から実機、内部テスト配信まで一手でつながった日に、私が手放さなかったもの — AI Studio の一気通貫を個人開発の配信フローに据える
AI Studio がテキストから Kotlin/Compose アプリを生成し、エミュレータ・実機・Play 内部テストまで一画面でつなぐようになりました。便利さの裏で「配信の瞬間」をどこまで機械に預け、どこを自分の手で握るか。個人開発で複数アプリを抱える立場からの線引きと、その境界を支える実装をまとめました。
アプリ開発2026-05-03
io.github.sceneview を使った Antigravity AR 開発入門——AnchorNode のエラーを乗り越えて
SceneView(io.github.sceneview)を使ってAndroidのAR機能を実装する方法を解説。AnchorNodeのエラー対処、ARCoreのインストール処理、平面検出の可視化、Antigravity AIを組み合わせたシーン生成まで、実機で詰まった箇所を中心に紹介します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →