概要
Flutterでアプリをビルドする際には、本番環境と開発環境でGoogleService-info.plist
等の設定ファイルの切り替えが必要となるケースが多いと思います。
この切替には複数のSchemeを用意する方法、Flavor
を使う方法、ビルド時の--release
と--debug
を使って切り分ける方法がありますが、Flutter 1.17からビルド引数の--dart-define
で定数を渡せるようになりました。
この--dart-define
を使ってGoogleService-info.plist
を切り替えてみましょう。
前提
- Flutterのサンプルプロジェクトを作成しシミュレーターで実行できる
- Flutter 1.20以降
-
--dart-define
の設定ができる(こちらの記事を参照)
環境
$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 1.22.4, on Mac OS X 10.15.7 19H2 darwin-x64, locale en-JP)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 12.1)
[✓] Android Studio (version 4.1)
[✓] Connected device (1 available)
iOS用の設定
iOSの場合、本番環境用と開発環境用のGoogleService-info.plist
をビルド時のスクリプトで切り替える方法となります。
Flutterの設定
以下のように、コンパイル引数で渡します。
開発用
flutter build ios --dart-define=DEFINE_BUILD_ENV=dev
本番用
flutter build ios --dart-define=DEFINE_BUILD_ENV=prod
※ --dart-define の基本的な設定についてはこちらの記事を見てください。
Xcodeの設定
Runner
の中にFirebase
というフォルダを作り、その中にGoogleService-Info.plist
を(開発用はGoogleService-Info-Dev.plist
、本番用はGoogleService-Info-Prod.plist
という名前で)追加します。
またRunner
ディレクトリにGoogleService-Info.plist
を追加しTargetに追加しておきます。(中身は開発用でも本番用でも、どちらでも大丈夫で、Keyだけ残して値は消してしまっても問題ありません。)
次にBuild Phases
を開き+
を押してNew Run Script Phase
を追加します。名前をわかりやすいように変え、既存のRun Script
の下に移動させます。(Script名をSelect Firebase Environment
としました。)
Scriptに以下を追加します。定数については--dart-define
を使っています。設定についてはこちらの記事を参考にしてください。
if [[ $DEFINE_BUILD_ENV == *"dev"* ]]; then
cp $PRODUCT_NAME/Firebase/GoogleService-Info-Dev.plist $PRODUCT_NAME/GoogleService-Info.plist
elif [[ $DEFINE_BUILD_ENV == *"prod"* ]]; then
cp $PRODUCT_NAME/Firebase/GoogleService-Info-Prod.plist $PRODUCT_NAME/GoogleService-Info.plist
else
echo "configuration didn't match to 'dev' or 'prod'"
echo "Your DEFINE_BUILD_ENV is '$DEFINE_BUILD_ENV'"
exit 1
fi
動作確認
DEFINE_BUILD_ENV
の値を開発用、本番用、どちでもない、で確認してみてください。どちらでもない値の場合はビルドエラーが発生し、エラーメッセージが表示されると思います。
android用の設定
androidの場合も、本番環境用と開発環境用のgoogle-services.json
をビルド時のスクリプトで切り替える方法となります。
Flutterの設定
以下のように、コンパイル引数で渡します。
開発用
flutter build apk --dart-define=DEFINE_BUILD_ENV=dev
本番用
flutter build apk --dart-define=DEFINE_BUILD_ENV=prod
※ --dart-define の基本的な設定についてはこちらの記事を見てください。
gradleの設定
[project]/android/app/src/config
を作成し、その中にdev
とprod
ディレクトリを作成します。その中に、開発用、本番用のgoogle-services.json
を設置します。
[project]/android/app/build.gralde
を以下のように編集します。
// 〜〜 省略 〜〜
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
// ここから追記 --
def dartEnvironmentVariables = [
DEFINE_BUILD_ENV: 'dev',
];
if (project.hasProperty('dart-defines')) {
dartEnvironmentVariables = dartEnvironmentVariables + project.property('dart-defines')
.split(',')
.collectEntries { entry ->
def pair = URLDecoder.decode(entry).split('=')
[(pair.first()): pair.last()]
}
}
// firebaseファイルをコピーして android/app ディレクトリに移動
def googleServicesJson = "src/config/${dartEnvironmentVariables.DEFINE_BUILD_ENV}/google-services.json"
task copyGoogleServicesJson(type: Copy) {
from googleServicesJson
into './'
if(inputs.sourceFiles.empty){
throw new StopExecutionException("No files found: ${googleServicesJson}")
}
}
// firebaseファイルのコピータスクを待ってからファイルが必要な処理を行うよう設定
tasks.whenTaskAdded { task ->
if (task.name == 'processDebugGoogleServices') {
task.dependsOn copyGoogleServicesJson
}
if (task.name == 'processReleaseGoogleServices') {
task.dependsOn copyGoogleServicesJson
}
}
// ここまで追記 --
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
動作確認
DEFINE_BUILD_ENV
の値を開発用、本番用、どちでもない、で確認してみてください。どちらでもない値の場合はビルドエラーが発生し、エラーメッセージが表示されると思います。