Flutterfire CLI で Flutter x Firebase の環境分けをする
はじめに
皆さんは普段の Flutter 開発において、どのように環境を用意していますか?
特に、Firebase を利用しているプロジェクトにおいてはプラットフォームごとの設定ファイルの扱いもあり少し手間かと思います。
今回は、Flutterfire CLI を使った以下の記事のような方法がとても良いと思ったのでご紹介します。
flutter_flavorizr 導入
Flutterfire CLI
を使った環境分けには、flutter run --flavor dev
のように flavor オプションによるアプリビルドが必要になります。
flutter_flavorizr
というパッケージを利用することで、この設定をとてもスムーズに行うことが出来ます。
前提
このパッケージの利用については、既存プロジェクトにおいて過去に行っていた設定を想定外に上書きしてしまう可能性があるため、新規プロジェクトでの利用が推奨されています。
iOS 環境構築には以下が必要になります:
初期設定
まずは Flutter プロジェクトを作成しましょう。
flutter create flavor_sample_app --empty
pubspec.yaml
に flutter_flavorizr
を追加します:
dev_dependencies:
flutter_flavorizr: ^2.2.3
プロジェクトルートに flavorizr.yaml
というファイルを作成し、以下のように記載します:
flavors:
dev:
app:
name: "Flavor Sample App Dev"
android:
applicationId: "com.example.flavor_sample_app.dev"
ios:
bundleId: "com.example.flavorSampleApp.dev"
prod:
app:
name: "Flavor Sample App"
android:
applicationId: "com.example.flavor_sample_app"
ios:
bundleId: "com.example.flavorSampleApp"
ここでは、dev
と prod
の2つの環境を用意しています (stg
環境も必要な場合は dev
同様に追加してください)。
以下のコマンドを実行することで、諸々の設定を全て一括で行なってくれます:
dart run flutter_flavorizr
ビルド引数設定
上記の実行だけで、以下コマンドのように環境ごとのアプリがビルド出来るようになります:
flutter run --flavor dev -t lib/main_dev.dart
flutter run --flavor prod -t lib/main_prod.dart
実際にビルドしてみると、以下のように flavor ごとのアプリがビルドされます:
本番環境 | 開発環境 |
---|---|
尚、flutter run --flavor dev -t lib/main_dev.dart
のようなビルド引数を、flavorizr.yaml
から IDE へ設定することが出来ます。
VS Code を利用している場合:
ide: "vscode"
flavors:
dev:
# ...
Android Studio や IntelliJ IDEA を利用している場合:
ide: "idea"
flavors:
dev:
# ...
上記のように記載後、以下のコマンドを実行します:
dart run flutter_flavorizr -p ide:config
アイコン設定
ここまでを行えば一通りの環境分けは完了ですが、例えば以下のように環境ごとにアイコンを設定することも可能です。
本番環境 | 開発環境 |
---|---|
それぞれのプラットフォーム向けに作成した画像を assets
ディレクトリ内に格納し、そのパスを flavorizr.yaml
に記載します。
ide: "idea"
flavors:
dev:
app:
name: "Flavor Sample App Dev"
android:
applicationId: "com.example.flavor_sample_app.dev"
+ icon: "assets/android_app_icon_dev.png"
+ adaptiveIcon:
+ foreground: "assets/android_app_icon_foreground_dev.png"
+ background: "assets/android_app_icon_background.png"
ios:
bundleId: "com.example.flavorSampleApp.dev"
+ icon: "assets/ios_app_icon_dev.png"
prod:
app:
name: "Flavor Sample App"
android:
applicationId: "com.example.flavor_sample_app"
+ icon: "assets/android_app_icon.png"
+ adaptiveIcon:
+ foreground: "assets/android_app_icon_foreground.png"
+ background: "assets/android_app_icon_background.png"
ios:
bundleId: "com.example.flavorSampleApp"
+ icon: "assets/ios_app_icon.png"
Android 用アイコンを反映させるために以下のコマンドを実行します:
dart run flutter_flavorizr -p android:icons
すると、各サイズの画像生成や dart run flutter_flavorizr
で生成されていたダミーのアイコン画像からの置き換えをよしなにしてくれます:
iOS 側も同様に以下のコマンドを実行します:
dart run flutter_flavorizr -p ios:icons
Firebase プロジェクトの準備
上記のページから、環境ごとの Firebase プロジェクトを作成します:
FlutterFire CLI 導入
インストール
Firebase の環境設定には iOS 用の GoogleService-Info.plist
や Android 用の google-services.json
が必要になります。
これらのファイルは各環境の Firebase プロジェクトごとにコンソールからダウンロードする必要がありますが、FlutterFire CLI を利用することでこの手順を簡略化することが出来ます。
まずは、前段階として firebase --version
コマンドでバージョンが表示されない場合、Firebase CLI をインストールします:
npm install -g firebase-tools
以下のコマンドで Firebase プロジェクトを作成したアカウントへログインします:
firebase login
以下コマンドで FlutterFire CLI (1.0.0
以上が必要) をインストールします:
dart pub global activate flutterfire_cli
※ 過去にインストール済みの場合でも、依存関係が原因で再実行が必要な場合があります
コマンド実行
実際に各環境ごとに以下コマンドを実行していきます。
dev 環境の場合:
flutterfire config \
--project=flavor-sample-app-dev \
--out=lib/firebase_options_dev.dart \
--ios-bundle-id=com.example.flavorSampleApp.dev \
--ios-out=ios/flavors/dev/GoogleService-Info.plist \
--android-package-name=com.example.flavor_sample_app.dev \
--android-out=android/app/src/dev/google-services.json
prod 環境の場合:
flutterfire config \
--project=flavor-sample-app-prod \
--out=lib/firebase_options_prod.dart \
--ios-bundle-id=com.example.flavorSampleApp \
--ios-out=ios/flavors/prod/GoogleService-Info.plist \
--android-package-name=com.example.flavor_sample_app \
--android-out=android/app/src/prod/google-services.json
-
--project
は、自身の Firebase プロジェクト ID を指定します -
--ios-bundle-id
は、iOS のバンドル ID を指定します -
--android-package-name
は、Android の ApplicationId を指定します
実際にコマンドを実行すると、プロンプトが表示されるので、それに沿って回答していきます。
Build configuration
を選択します:
? You have to choose a configuration type. Either build configuration (most likely choice) or a target set up. ›
❯ Build configuration
Target
ここでエラーが出てしまったら...
Exception: /Users/masaki/.rbenv/versions/3.2.2/lib/ruby/site_ruby/3.2.0/rubygems/specification.rb:2242:in `check_version_conflict': can't activate rexml-3.2.8, already activated rexml-3.4.0 (Gem::LoadError)
上記のようなエラーが出てしまった場合、gem によりインストールされた xcodeproj
と rexml
のバージョンが競合している可能性があります。
gem list rexml
によりインストール済みの rexml
を確認し、xcodeproj --version
と互換性の無いものを以下のように削除しましょう:
gem uninstall rexml --version 3.2.8
dev
環境の場合は Debug-dev
、prod
環境の場合は Debug-prod
を選択します:
? Please choose one of the following build configurations ›
Debug
Release
Profile
❯ Debug-dev
Profile-dev
Release-dev
Debug-prod
Profile-prod
Release-prod
設定したいプラットフォームを選択します:
? Which platforms should your configuration support (use arrow keys & space to select)? ›
✔ android
✔ ios
macos
✔ web
windows
処理が完了すると以下のように、プロジェクト上にアプリが作成されています:
また、コマンド上で指定したアウトプット先に firebase_options.dart
、GoogleService-Info.plist
、google-services.json
が作成されています。
firebase_core パッケージ導入
ここからは、実際にアプリをビルドするための準備をしていきます。
firebase_core
パッケージをインストールします:
flutter pub add firebase_core
iOS プラットフォームバージョンは 13.0
以上にする必要があるため、ios/Podfile
にて以下のように設定します:
# Uncomment this line to define a global platform for your project
platform :ios, '13.0'
Firebase 初期化
実際に Dart ファイル内で Firebase を初期化しましょう。
今回はエントリーポイントを環境ごとに用意しているため、以下のコマンドでビルド出来るように設定します:
flutter run --flavor dev -t lib/main_dev.dart
flutter run --flavor prod -t lib/main_prod.dart
エントリーポイントとなる main._*.dart
ファイルにて、FirebaseOptions を import します:
import 'package:flavor_sample_app/firebase_options_dev.dart';
import 'flavors.dart';
import 'main.dart';
void main() async {
F.appFlavor = Flavor.dev;
runMainApp(DefaultFirebaseOptions.currentPlatform);
}
import 'package:flavor_sample_app/firebase_options_prod.dart';
import 'flavors.dart';
import 'main.dart';
void main() async {
F.appFlavor = Flavor.prod;
runMainApp(DefaultFirebaseOptions.currentPlatform);
}
そして、main.dart
では FirebaseOptions を受け取って Firebase の初期化処理を実行出来るようにします:
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'app.dart';
void runMainApp(FirebaseOptions firebaseOptions) async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(options: firebaseOptions);
runApp(const App());
}
終わりに
お疲れ様でした!
色々とプラットフォームごとのファイルをいじる必要がなく、とてもシンプルに環境構築が出来たかと思います。
修正箇所等ありましたら、コメントでお知らせいただけますと幸いです🙌
参考記事
Discussion