2026-08-17 公開 / アプリ開発
ブラウザゲームをCapacitorでAndroidアプリにして公開するまでに踏んだ地雷
HTMLとJavaScriptで動くゲームを、Capacitor で包んで Google Play に出しました。「既にあるWebアプリをそのままアプリにできる」という説明は本当ですが、そのまま出せたのはビルドまでで、そこから先に地雷がいくつも埋まっていました。順に書きます。
地雷1: 権限を1つ持っているだけで、対応デバイスが0台になる
これがいちばん怖かったやつです。ビルドは通り、アップロードも通り、審査も通ったのに、ストアの管理画面で対応デバイスが0台と表示されます。誰もインストールできません。
原因は、広告や計測に関わるプラグインが自動で追加する権限でした。ライブラリ側のマニフェストに書かれているので、自分では1行も書いていないのに入ります。マージされた結果を見るまで気づけません。
対処は、アプリ側のマニフェストで該当の権限を明示的に除去することです。Android のマニフェストマージには「ライブラリが足した要素を削る」指定があるので、それを使います。
教訓としてはこちらのほうが大事: ビルドが通ることと、配信できることは別です。アップロードしたあと、公開前に「対応デバイス数」を必ず見る。0台ならそこで止まります。私はこれをチェックリストに入れて、以降は毎回見ています。
地雷2: バージョン番号は上げるしかない。下げられない
Android アプリには、ストアが識別に使う内部的な連番があります。これは一度アップロードした値より小さい値は、二度と使えません。取り消しもできません。
何が起きるかというと、テストのつもりでアップロードしたビルドで番号を消費し、次の本番ビルドで番号が飛びます。飛ぶだけなら問題ないのですが、手元のプロジェクトの値とストア側の値がずれた状態でリリース作業に入ると、必ず一度アップロードを弾かれます。そして焦って適当な値に上げると、次はもっとずれます。
これを直したのは技術ではなく管理でした。「次に使う番号」を全アプリ分まとめて1つのファイルに書いて台帳にしました。ビルドの前にそこを見て、+1して、台帳も同時に更新します。アプリが増えると記憶では追えません。
地雷3: ブラウザで動いていたものが、アプリの中では動かない
Capacitor の中身は WebView なので、ブラウザと同じだろうと思っていました。実際に差が出たのは主にこの3つです。
- タッチイベント。ブラウザでは想定どおりだった長押し・スワイプの扱いが、WebView では選択やスクロールに取られることがある
- 画面サイズの取得。ブラウザのアドレスバーを前提にした高さの計算が、アプリだと余白やノッチの分でずれる
- 初回の描画タイミング。ブラウザより起動が速いぶん、リソースの読み込み完了を待たずに描画に入って一瞬崩れる
どれも実機で触るまで気づきませんでした。エミュレータでは再現しなかったものもあります。結果として「実機1台で必ず一周触る」を工程に入れました。地味ですが、ここを飛ばすと必ず戻ってきます。
地雷4: Webアセットを反映し忘れたまま、平然とビルドが通る
Capacitor は Web側のファイルを Android プロジェクトにコピーして使います。つまり、Web側を直しただけではアプリに反映されません。コピーの工程を挟む必要があります。
厄介なのは、忘れてもビルドが成功することです。エラーは出ません。古い中身のアプリが正常にできあがります。「直したのに直っていない」と言いながら、直っていない古いファイルを何度もビルドすることになります。
対処は工程の固定です。「Web側を直したら、コピー→ビルド」を1つの手順としてまとめて、途中から入らないようにしました。失敗が静かに起きる工程は、記憶に任せてはいけないという一般則の一例だと思います。
地雷5: 広告のIDを差し替える場所が1つではない
テスト用の広告IDから本番のIDに差し替えるとき、1箇所直せば済むと思っていたら3箇所ありました。設定ファイル、Androidのマニフェスト、そしてアプリ内で広告を表示している箇所です。
1つ残っていても動きます。ただしテスト用IDのままなので収益がゼロのまま正常に動きます。これも静かに失敗する類です。差し替え箇所を数えて手順に書き出すまで、毎回どこか漏れていました。
AIにどう作らせたか
ゲーム本体のコードは AI(Claude)にかなり書かせています。この工程で効いた指示の出し方が2つありました。
1つめ: 「動くものを作って」ではなく「この制約の下で動くものを作って」と渡す。WebView で動くこと、外部通信をしないこと、画面サイズが可変であること、といった制約を先に列挙して渡すと、あとから直す量が明確に減りました。制約を言わずに作らせると、ブラウザ前提のコードが出てきて、地雷3を自分で踏みに行くことになります。
2つめ: 失敗した現象を、原因の推測ではなく症状のまま渡す。「タッチイベントの取り扱いがおかしいと思う」と伝えると、その仮説の上で修正が進みます。「長押しすると画面の文字が選択されて、ゲームの操作が効かなくなる」と症状で渡すと、こちらが思っていなかった原因を出してくることがありました。原因の切り分けを自分で先にやってしまうと、その切り分けの誤りごと引き継がれます。
逆に効かなかったのは、プロジェクト全体を渡して「良くして」と頼むことでした。返ってくる変更の量が多すぎて、どの変更がどの問題に対応しているのか追えなくなり、結局全部戻しました。
公開前チェックリスト
- Web側を直したら、アセットのコピー工程を通した
- 内部バージョン番号を台帳で確認して +1 し、台帳も更新した
- マージ後のマニフェストを見て、意図しない権限が入っていない
- アップロード後、公開前に対応デバイス数が0台でないことを確認した
- 広告IDを差し替える3箇所すべてを直した
- 実機1台で、起動から終了まで一周触った
- プライバシーポリシーのURLとスクリーンショットを用意した
まとめ
この工程で踏んだ地雷を並べてみると、4つが「失敗しても何も言われない」タイプでした。対応デバイス0台、古いアセットのままビルド成功、テスト用広告IDのまま正常動作、番号のずれ。どれもエラーにならず、正常に完了したように見えます。
だから対策も同じ形になりました。エラーが出ないところに、自分で確認の工程を置く。技術的な難しさより、ここを手順として固定できるかどうかのほうが効きました。