はじめに
こんにちは!個人開発で冷蔵庫管理アプリ FridgeManager を作っているエンジニアです。 アプリの収益化のためにGoogle AdMobのバナー広告(react-native-google-mobile-ads)を導入したのですが、「起動直後にアプリが繰り返し停止(クラッシュ)する」という深い沼にハマってしまいました。
今回は、公式ドキュメントやエラーログの誤解を解き明かし、TypeScript環境かつ環境変数(.env)を使って、開発環境(Dev)と本番環境(Prod)の広告IDをスマートに切り替える完全な解決策をまとめました。
同じエラーで足止めを食らっている方の参考になれば幸いです!
1. 開発環境とやりたかったこと
- フレームワーク: Expo (React Native) / TypeScript
- 使用ライブラリ:
react-native-google-mobile-ads(※expo-ads-admobは非推奨のため、これが現在の標準です) - 実現したいこと: 開発中はテスト用ID、本番ビルド(EAS Build)時は本番用IDを
.envから自動で切り替える。
2. 【大苦戦】アプリが起動直後に「繰り返し停止」する原因
AdMobの初期実装を終え、いざローカルで開発ビルド(npx expo run:android)を立ち上げると、画面が開く前にアプリが強制終了。ログには以下のような警告やエラーが出ていました。
WARNING: react-native-google-mobile-ads requires an 'android_app_id' property inside a 'react-native-google-mobile-ads' key in your app.json.No 'androidAppId' was provided. The native Google Mobile Ads SDK will crash on Android without it.
Google Mobile Ads SDKは、ネイティブ側に有効なアプリIDがセットされていないと、安全のためにアプリを強制終了させる仕様になっています。
当初は「.env が読めていないのでは?」と疑いましたが、検証すると環境変数は正しく読み込まれていました。では、なぜネイティブ側にIDが伝わっていなかったのでしょうか?
犯人は「エラーログの罠」と「キー名の不一致」
非Expoアプリ(生のReact Native)向けの警告ログに引っ張られ、app.config.ts の中で android_app_id(スネークケース)と記述してしまっていました。
しかし、ExpoのConfig Pluginが内部で認識する正しいプロパティ名は androidAppId(キャメルケース) でした。キー名が違ったため、プラグインがIDを認識できず、結果として中身が空(undefined)のままAndroidのビルドが進んでしまっていたのです。
さらに、android フォルダ内に古いキャッシュ(空のIDの状態)が残っていたことも、状況を悪化させる原因でした。
3. 解決した完全な実装コード
この問題を根本から解決し、.env から安全にIDを切り替える正しい設定手順がこちらです。
① 環境変数ファイル(.env)の作成
ルートディレクトリに開発用と本番用のファイルを分けて作成します。Expoの仕様上、接頭辞 EXPO_PUBLIC_ が必須です。
Ini, TOML
# .env.development(開発・テスト用)
EXPO_PUBLIC_ADMOB_APP_ID=ca-app-pub-3940256099942544~3347511713
EXPO_PUBLIC_ADMOB_BANNER_ID=ca-app-pub-3940256099942544/6300978111
# .env.production(本番用)
EXPO_PUBLIC_ADMOB_APP_ID=ca-app-pub-xxxxxxxxxxxxxxxx~xxxxxxxxxx
EXPO_PUBLIC_ADMOB_BANNER_ID=ca-app-pub-xxxxxxxxxxxxxxxx/xxxxxxxxxx
② app.config.ts の修正(最重要)
プラグインのキー名を正しいキャメルケース(androidAppId)で指定します。
TypeScript
import { ConfigContext, ExpoConfig } from "@expo/config";
export default ({ config }: ConfigContext): ExpoConfig => ({
...config,
name: "MyApp",
slug: "MyApp",
// ...中略...
android: {
package: "com.yourname.MyApp",
// local.properties で Android SDK のパスを指定しておくとビルドが安定します
},
plugins: [
[
"react-native-google-mobile-ads",
{
// 💡 正しいキー名「androidAppId」で環境変数を渡す
androidAppId: process.env.EXPO_PUBLIC_ADMOB_APP_ID,
},
],
],
});
③ 最新の適応型バナーコンポーネント(.tsx)
現在、公式ドキュメント(Google Mobile Ads SDK)で非推奨となった ANCHORED_ADAPTIVE_BANNER に代わり、推奨されている INLINE_ADAPTIVE_BANNER を使用した最新の実装です。
TypeScript
import React from 'react';
import { View, StyleSheet, Dimensions } from 'react-native';
import { BannerAd, BannerAdSize } from 'react-native-google-mobile-ads';
const adUnitId = process.env.EXPO_PUBLIC_ADMOB_BANNER_ID || '';
const { width: windowWidth } = Dimensions.get('window');
export default function AdBanner() {
return (
<View style={styles.adContainer}>
<BannerAd
unitId={adUnitId}
size={BannerAdSize.INLINE_ADAPTIVE_BANNER} // 最新の推奨設定
width={windowWidth} // 横幅を明示的に指定
requestOptions={{ requestNonPersonalizedAdsOnly: true }}
/>
</View>
);
}
const styles = StyleSheet.create({
adContainer: {
alignItems: 'center',
justifyContent: 'center',
width: '100%',
backgroundColor: '#fff',
},
});
4. 確実にネイティブへ反映させるリフレッシュ手順
設定を書き換えた後は、過去のビルドキャッシュを完全に吹き飛ばして再ビルドする必要があります。
Bash
# 古いネイティブフォルダを削除して完全に再ビルド
rm -rf android
npx expo run:android
※もしAndroid SDKのパスエラーが出る場合は、自動生成される android/local.properties に sdk.dir=/Users/【ユーザー名】/Library/Android/sdk のようにパスを手動で記述すると解決します。
これで警告メッセージ(No 'androidAppId' was provided.)が消え、アプリがクラッシュすることなく起動し、画面下部にAdMobのテストバナーが表示されるようになりました!
まとめ:ミスを防ぐポイント
- エラーログを鵜呑みにしない: プラグイン外の設定(
android_app_id)を求めるログに騙されず、Expoのプラグイン規則(androidAppId)に従う。 - 環境変数は
EXPO_PUBLIC_から始める: これがないとExpoが値を隠蔽してしまい、ネイティブ側でundefinedになります。 - 設定変更後は
androidフォルダを消して再ビルド: 浅いキャッシュに悩まされる時間を断捨離できます。 - アプリをリリースするためにビルドするならExpoの管理画面から環境変数を設定しないといけないので注意です。
本番リリース時は、eas.json の production プロファイルの env に本番用環境変数を指定して eas build を叩くだけで自動切り替えが完了します。
皆さんも安全でクリーンなAdMobライフをお送りください!


コメント