【Flutter】Firebase CLIで環境構築と環境分け

## 背景
複数の環境下でFirebaseにてプロジェクトを作成しており、各環境をFlutterのプロジェクトと紐づける機会があったのでその備忘録を記載します。

## 目標

Flutter CLIを使って、プロジェクトを開発環境（dev）と本番環境（pro）にそれぞれFirebaseと連携させる。

環境ごとの実行コマンドは以下とする
```
flutter run --flavor dev
flutter run --flavor pro
```

## パッケージのインストール

・firebase-toolsのインストール
```
$ curl -sL https://firebase.tools | bash
```

・pabspec.yamlに必要なパッケージを設定
```
dependencies:
  firebase_core: ^3.4.0
```
他は以下から必要なパッケージを設定しておく
https://firebase.google.com/docs/flutter/setup?hl=ja&platform=ios#available-plugins

今回使用パッケージ
```
dependencies:
  firebase_core: ^3.4.0
  firebase_analytics: ^11.3.0
```

## Firebaseにログイン
```
$ firebase login
$ dart pub global activate flutterfire_cli
```

## flutterfire configure実行
※crashlyticsを後から導入した場合は再度実行が必要です。

以下のコマンドを実行する
```
$ flutterfire configure
```

firebaseに存在するプロジェクト一覧が表示されるので、対象のプロジェクトを選択。
```
$ test_project % flutterfire configure
i Found 11 Firebase projects.                                 
? Select a Firebase project to configure your Flutter application with › application with › 
❯ 存在するアプリ一覧
  <create a new project>
```

androidとiosを選択する
```
✔ Select a Firebase project to configure your Flutter application with · 選択したアプリ名            
? Which platforms should your configuration support (use arrow keys & space to select)? ›                              
✔ android                                                     
✔ ios                                                           
  macos                                                         
  web                                                        
  windows     
```
コマンドでプロジェクトを指定することも可能
```
flutterfire congifure --project Firebaseのプロジェクト名 --android-app-id AndroidのAppID --ios-bundle-id iOSのバンドルID
```

上記を実行すると以下のファイルが作成される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3772194/d64dbae5-b0cf-d549-bba3-df8fec72814f.png)

## 環境ごとにファイルを再配置する
### それぞれの環境のFirebase用のファイルを以下で配置
![スクリーンショット 2024-09-02 18.49.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3772194/b4ae146d-b204-619d-39d1-87d095ab3b76.png)

一旦作成したファイルを上記のファイル配置を元に移動。
その後、再度flutterfire configureを実行し、もう一方のプロジェクトを選択すると、再度ファイルが作成されるのでそれぞれのファイルを配置する。
※ファイルを移動せずに実行すると、元のファイルは上書きされるので注意。



## firebase_options.dartの設定
main.dartに以下を記載する
```
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:test_project/dev_firebase_options.dart' as dev;
import 'package:test_project/pro_firebase_options.dart' as pro;

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  const flavor = String.fromEnvironment('FLAVOR');
  final firebaseOptions = flavor == 'pro'
      ? pro.DefaultFirebaseOptions.currentPlatform
      : dev.DefaultFirebaseOptions.currentPlatform;

  await Firebase.initializeApp(
    options: firebaseOptions,
  );
  runApp(const MyApp());
}
```
※options: firebaseOptionsは指定しなくても動くようだったので、
firebase_options.dartは不要かもしれない。

## google-service.jsonの設定
android/app/src配下にflavor名のフォルダを作成し、google-service.jsonを以下の様に配置するだけでOK。
flavorを指定してbuildすると、そのディレクトリを参照してくれる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3772194/f8898475-6827-172f-9838-7244c3499046.png)

## GoogleService-info.plistの設定
ios/Runner直下に各環境のGoogleService-info.plistをコピーする処理をBuild Phaseに設定する。

Build PhaseにScriptを追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3772194/d928ea0f-ad06-3669-1e0c-f83380f4a5f8.png)

Shellに以下のコードを追加する
```
if [[ $CONFIGURATION == *"dev"* ]]; then
    cp
        $PRODUCT_NAME/Firebase/dev/GoogleService-info.plist $PRODUCT_NAME/GoogleService-info.plist
elif [[ $CONFIGURATION == *"pro"* ]]; then
    cp
        $PRODUCT_NAME/Firebase/pro/GoogleService-info.plist $PRODUCT_NAME/GoogleService-info.plist
fi
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3772194/69b2398b-3764-fe86-54fa-9740ca2b4414.png)



### firebase.jsonの設定
firebase.jsonは、XCodeのBuild Phaseに作成された、
「Flutter Fire:"fluttrefire upload-crashlytics-symbols」で使用されている
![スクリーンショット 2024-09-02 19.21.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3772194/281fee2a-5ddf-a737-0ce9-9d9645306d78.png)

上記のスクリプトのflutterfire upload-crashlytics-symbols...でプロジェクト直下のfirebase.jsonファイルを参照しているので、スクリプト実行前にfirebase.jsonをプロジェクト直下にコピーする設定が必要。

firebase.jsonの場合と同様にBuild PhaseにScriptを追加
Shellに以下のコードを追加
```
if [[ $CONFIGURATION == *"dev"* ]]; then
    cp
        $PRODUCT_NAME/Firebase/dev/firebase.json ${PROJECT_DIR}/../firebase.json
elif [[ $CONFIGURATION == *"pro"* ]]; then
    cp
        $PRODUCT_NAME/Firebase/pro/firebase.json ${PROJECT_DIR}/../firebase.json
fi

```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3772194/2af948ee-faac-34f8-9763-721ab2315fa6.png)


上記のBuild Phaseを「Flutter Fire:"fluttrefire upload-crashlytics-symbols」より前に実行されるよう位置を移動する。


### エラーが出る場合

実行で以下のエラーが出る場合。
```
flutterfire: command not found Command PhaseScriptException failed with a nonzero exit code
```

「Flutter Fire:"fluttrefire upload-crashlytics-symbols」が表示されれば失敗している。
エラーを解消するためには次の作業を行う。

[Issue](https://github.com/invertase/flutterfire_cli/issues/257#issuecomment-2000473854)を参考に、前のスクリプトまたは、「Flutter Fire:"fluttrefire upload-crashlytics-symbols」スクリプトのflutterfire upload-crashlytics-symbols...実行前に以下を追加するとエラーが解消される
```
dart pub global activate flutterfire_cli
```
※「Flutter Fire:"fluttrefire upload-crashlytics-symbols」内だとflutterfire configure実行時に上書きされてしまうので前のスクリプトに記載するほうが良いかもしれない。


# 告知
最後にお知らせとなりますが、イーディーエーでは一緒に働くエンジニアを
募集しております。詳しくは採用情報ページをご確認ください。

https://eda-inc.jp/recruit/

みなさまからのご応募をお待ちしております。