ビルドは通ったのにアプリが起動しない?原因はAdMob設定の競合かも
「ようやくEASビルドが通った!さあ実機でテストしよう!」
そう思ってアプリをインストール → 起動した直後、一瞬でアプリが落ちるという現象が起きました。
ビルドは通っているだけに、「何が悪かったのか分からない」という状態になりがちですが、今回のケースでは以下のような典型的なミスが原因でした。
❗ 原因①:app.json
で AdMobアプリIDを二重設定していた
Expo + AdMob の構成では、アプリIDの指定方法が2種類あります。
plugins
で指定する(Expoが推奨)android.metaData
で手動で指定する
この両方にアプリIDを記述してしまうと、ビルド時に AndroidManifest.xml に同じ APPLICATION_ID
が2回挿入されてしまい、AdMob SDKがクラッシュを引き起こします。
💥 実際に起きたエラーログ:
Invalid application ID. Follow instructions here:
java.lang.RuntimeException: Unable to start activity ComponentInfo{...}: java.lang.IllegalStateException: APPLICATION_ID is missing
これ、最初は「設定したはずなのに、なぜ ‘missing’?」と思うかもしれませんが、“2回設定されていて不正になった” というケースがほとんどです。
✅ 解決方法:AdMob IDは plugins
にだけ書く
Expo Managed Workflowを使っている場合は、AdMobの設定は必ず app.json
の plugins
に1箇所だけ記述するのが正しい方法です。
"plugins": [
[
"react-native-google-mobile-ads",
{
"android_app_id": "ca-app-pub-3940256099942544~3347511713",
"ios_app_id": "ca-app-pub-3940256099942544~1458002511",
"user_tracking_usage_description": "この識別子は、パーソナライズされた広告を提供するために使用されます。"
}
]
]
そして、android.metaData
のような手動設定は完全に削除します:
"android": {
- "meta-data": {
- "com.google.android.gms.ads.APPLICATION_ID": "xxx"
- }
}
Expoが自動で必要な meta-data
を生成してくれるため、自分で書く必要はありません。
🔁 修正後のフロー
app.json
の設定ミスを修正(metaData
削除)- キャッシュをクリアしつつ再ビルド:
eas build --clear-cache --platform android
- 実機にインストールして起動確認
アプリが正常に起動し、ログに AdMob initialized
などが表示されていればOKです。
🧱 AdMobの初期化忘れでクラッシュ?コードに1行足りてません
ビルド成功、設定も完了していたはずなのに、アプリがなぜか起動直後に落ちる or 広告表示で落ちるという場合。
それ、もしかして mobileAds().initialize()
を忘れていませんか?
AdMob SDKは、アプリが起動したタイミングで一度だけ初期化する必要があります。この初期化処理を入れていないと、広告表示の際にSDKが正しく動作せず、そのまま例外を投げてアプリを強制終了させます。
❌ 初期化を忘れるとこうなる(エラー例)
java.lang.RuntimeException: The Google Mobile Ads SDK was not initialized correctly.
もしくは、何も表示されないままアプリがフリーズ・終了するなどの症状が見られます。
このエラーは見た目上は「原因不明」に見えるため、初期化処理の漏れは気づきにくい落とし穴です。
✅ 解決策:useEffect
内でAdMobを初期化する
React NativeアプリのApp.js
やルートコンポーネントに以下のようなコードを追加してください:
import mobileAds from 'react-native-google-mobile-ads';
import { useEffect } from 'react';
useEffect(() => {
mobileAds()
.initialize()
.then(() => {
console.log("✅ AdMob initialized");
})
.catch(error => {
console.log("❌ AdMob initialization error:", error);
});
}, []);
この処理は、アプリのライフサイクルの最初(マウント時)に1回だけ実行されるようにしておく必要があります。
何回も呼んでも意味がないので、useEffect
の依存配列は空でOKです。
💡 ワンポイント:ログは積極的に入れておくと安心
初期化が失敗していた場合、コンソールログが唯一の手がかりになります。特にAndroidの実機では、エラーが画面上に出ないことも多いため、console.log()
や adb logcat
を使って確認しましょう。
よし、じゃあ次は「クイズ終了時にインタースティシャル広告を表示する処理」について、具体的なコード例と合わせて解説していくよ。実装にあたっての注意点も含めて、初心者でも追える構成でまとめてみる。
🎯 クイズ終了後に広告を表示:インタースティシャル広告の導入手順
アプリのクイズが終わったタイミングで、全画面広告(インタースティシャル広告)を表示したい場合、AdMobの提供するAPIを使って簡単に実装できます。
ここでは react-native-google-mobile-ads
を使った実装例を紹介します。
① 必要なモジュールをインポート
まずは、AdMobの広告表示に必要なコンポーネントとイベントタイプをインポートします。
import { InterstitialAd, AdEventType, TestIds } from 'react-native-google-mobile-ads';
開発中は TestIds.INTERSTITIAL
を使って、Google公式のテスト広告を表示するのがルールです。
本番用のIDはリリース直前に切り替えるようにしましょう。
② インスタンスの作成と読み込み
アプリ起動時に広告をあらかじめ読み込んでおきます。
これにより、ユーザーがクイズを終えたタイミングでスムーズに広告を表示できます。
const interstitial = InterstitialAd.createForAdRequest(TestIds.INTERSTITIAL, {
requestNonPersonalizedAdsOnly: true, // GDPR対応(EU圏など)
});
次に、useEffect
の中でイベントリスナーと広告読み込みを行います。
useEffect(() => {
const unsubscribe = interstitial.addAdEventListener(AdEventType.CLOSED, () => {
console.log('🔁 広告を閉じました');
// 必要ならここで画面遷移やステート更新処理も可能
});
interstitial.load(); // 起動時に読み込む
return unsubscribe; // コンポーネントがアンマウントされたらクリーンアップ
}, []);
③ クイズ終了時に広告を表示する
最後に、クイズが終わったタイミングで広告を表示します。
例えば、handleNext()
関数の中で次のように記述します:
const handleNext = () => {
setSelectedOption(null);
setShowFeedback(false);
if (currentIndex < quizData.length - 1) {
setCurrentIndex(currentIndex + 1);
} else {
setQuizFinished(true); // クイズ終了
// インタースティシャル広告を表示
if (interstitial.loaded) {
interstitial.show();
} else {
console.log('⚠️ 広告はまだ読み込まれていません');
}
}
};
これで、ユーザーが最後の問題を解いた直後に広告が表示される流れが実現できます。
よし、それじゃラスト近づいてきたね。
次は「実機クラッシュ時に使えるログ確認方法」、特に adb logcat
を使ったエラーの見つけ方について、シンプルで使える内容にまとめていくよ。
🧪 クラッシュ時の調査に役立つ adb logcat
の使い方
アプリが実機でクラッシュしたとき、「何が起きてるのか全然分からない…」ってなりがちですよね。
でも、Androidには強力なログツールがあって、クラッシュの原因がかなり高い精度で追えます。それが adb logcat
です。
✅ adb logcat
の基本
まずはAndroidデバイスをPCにつないだ状態で、次のコマンドを実行:
adb logcat
この時点で端末の内部ログがずらーっと流れてきます。
が、多すぎて読めないので、特定のキーワードで絞り込みます。
🛠 例:AdMob関連エラーを探す
adb logcat *:E | findstr /i "invalid application"
このコマンドは、エラーレベル(:E
)のログだけを表示し、その中から invalid application
を含む行だけを表示します。
AdMobの設定ミスによく出てくるのがこのワードです。
E/Ads: Invalid application ID. Follow instructions here:
↑これが出たら、app.json
の AdMobアプリIDの記述(meta-data
と plugins
の重複など)をまず疑ってください。
🖥 Android Studio派の人は Logcat ウィンドウでもOK
Android Studioを使っているなら、Logcat
タブを開いて次のように設定すると便利です:
- Log level: “Error”
- Filter by: App Package や “AdMob”、”GoogleMobileAds” などのキーワード
GUIでリアルタイムにログを確認できるので、コマンドラインが苦手な人はこちらでも十分対応可能です。
💡 ついでにやっておくといいこと
- クラッシュ後は アプリをアンインストールして再インストール すると、古いキャッシュや状態の影響を避けられます。
- エラーが再現できる操作手順(何をしたら落ちるか)を1つずつ整理しておくと、原因特定がぐっと楽になります。
console.log()
の活用も忘れずに。ビルド後でもReact Nativeのログは出力されます。
ありがとう。じゃあここで締めのまとめ、「ビルド後に起きた問題の総括」と「次回に活かすためのチェックリスト」で記事を締めくくるよ。落ち着いたトーンで、でも読者が実際に開発中にチェックリストとして使えるように構成するね。
✅ ビルド後トラブルの総まとめと、次回に活かすためのチェックリスト
EASビルドが無事に通っても、アプリが正常に動くとは限りません。特にAdMobのようなネイティブ連携系のライブラリは、設定ミスや初期化の抜けで実機起動後にクラッシュするケースが多いです。
今回のトラブルを通じて分かったこと、そして再発を防ぐために、以下のようなチェックポイントを用意しておくと安心です。
📌 再発防止チェックリスト
AdMobの設定関連
- [ ]
app.json
のplugins
にだけ AdMobのアプリIDを設定している(meta-data
は削除済み) - [ ] AndroidとiOSのアプリIDを分けて明記している
- [ ]
expo start --clear
もしくはeas build --clear-cache
を使ってキャッシュを一度リセットしている
初期化処理の実装
- [ ]
mobileAds().initialize()
をアプリ起動時に呼び出している - [ ]
useEffect
の中に1回だけ実行されるよう記述している - [ ] 初期化後のログやエラーキャッチも記述している(デバッグのため)
広告表示の処理
- [ ] インタースティシャル広告のインスタンスを生成して、クイズ終了時に表示する設計にしている
- [ ]
interstitial.load()
の呼び出しをアプリ起動後すぐに実装している - [ ]
interstitial.loaded
の判定を忘れていない(読み込み完了チェック)
テストとログの確認
- [ ] テスト用広告ID(
TestIds.INTERSTITIAL
など)を使っている(本番広告IDは使わない) - [ ] 実機で
.apk
をインストールして広告の表示を確認した - [ ]
adb logcat
でクラッシュ時のエラーを確認し、Invalid application ID
やSDK not initialized
のようなメッセージがないかチェックした
🧠 最後に
React Native + Expo + AdMob の組み合わせは、比較的構築しやすい一方で、設定ミス1つでビルドは通ってもクラッシュするという繊細な面もあります。
とはいえ、一度正しく構成しておけば、その後はスムーズに動作する安定した環境が手に入ります。今回の経験とチェックリストが、次回の実装やチーム開発時に役立つ「トラブル防止のマニュアル」になれば幸いです。
コメント