爆速でFlutterからFirestoreを使えるようにするまでの手順書



# モチベーション

* `Flutter+Firebase`の構成でアプリを作るときに、毎回やってる作業なので、自分のために手順をまとめておこうと思った

# 環境
* Mac OSX Catalina(10.15.7)

```shell
% firebase --version
8.13.1

% flutter --version
Flutter 1.24.0-3.0.pre • channel dev • https://github.com/flutter/flutter.git
Framework • revision 2783f8e2e1 (3 days ago) • 2020-10-22 09:36:06 -0700
Engine • revision defa8be2b1
Tools • Dart 2.11.0 (build 2.11.0-242.0.dev)
```

# マシンで1回だけやっておけば良いこと

## direnv/firebase-cliのインストール

```shell
$ brew install direnv firebase-cli
```

# アプリ毎にやること

## 環境変数の確認
```bash
# アプリのRoot
$ pwd
~/git/hogeApp

# hogeApp直下にdirenv用の.envrcをこんな感じに置いておく
$ cat .envrc
export YOUR_DOMAIN=com.example  # Flutterのorganizerに使用。逆から書くアレ。
export APP_NAME=hoge            # アプリ名(=Flutterのフォルダ名, BundleIDに使われる)

# 上記の場合、Bundle IDは com.example.hoge になる

# Firebaseの認証情報をこのプロジェクト以下で固定させる
$ echo "export XDG_CONFIG_HOME=`pwd`/.config" >> .envrc
# こうすると ~/git/hogeApp 以下のフォルダでfirebaseコマンドを叩くと、どこでも同じ認証情報を見てくれる

# 設定した.envrcを有効化
$ direnv allow
```

## Flutterアプリの作成

```bash
# --orgオプションを忘れると大変面倒なので忘れずに
$ flutter create --org ${YOUR_DOMAIN} ${APP_NAME}
```
* `~/git/hogeApp/hoge` がFlutter用のプロジェクトディレクトリとして作成される

## Firebase Projectの作成

* Firebaseでは、1つのProjectの下に複数のFirebaseアプリがぶら下がる。
* iOS/Android/Webがそれぞれ別にFirebaseアプリとして登録する必要がある。 

### 準備

```bash
#ディレクトリ堀って移動
$ mkdir firebase && cd $_

# firebaseへログイン（ブラウザが開くのでアカウント選択して許可をする）
$ firebase login
```

### いざ`firebase init`
1. `firebase init`を叩いて、`Emulators`だけONにする(**Firestoreを選択してはいけない**）
![スクリーンショット 2020-10-25 16.34.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26446/b304f527-5572-9739-ec45-23ce949f6c44.png)
2. `Create a new Project`を選択
![スクリーンショット 2020-10-25 16.33.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26446/eb223e7a-7632-e712-9964-44cf9658d04e.png)

3. `Firestore Emulator`を選択して、あとはEnter連打
![スクリーンショット 2020-10-25 16.40.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26446/859a440c-220a-1006-f058-ab9a4028e862.png)

4. うまくいけばこんな感じ
![スクリーンショット 2020-10-25 16.44.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26446/81672518-2fbd-de86-a86c-798b3606995b.png)

## Firestoreの初期化

* ブラウザからじゃないとできないので

```shell
# ブラウザが開く。便利！
$ firebase open firestore
```

1. どまん中の「データベースの作成」ボタンを押す
![スクリーンショット 2020-10-25 16.46.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26446/09a84665-4801-8605-169e-5c68ffbd6816.png)

2. とりあえずはテストモードでも良い
![スクリーンショット 2020-10-25 16.49.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26446/c0bd0b01-9512-6762-4c0d-deeaa514ad02.png)

3. リージョンは**asia-northeast1(Tokyo)**にするのを忘れずに
![スクリーンショット 2020-10-25 16.47.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26446/9989d727-8095-7d26-01ad-db69a712f405.png)

４. ターミナルに戻り、再び`firebase init`。設問で`Firestore`をスペースキーで選択状態にしてEnter
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26446/fd0ea156-06d7-49fb-8aec-e78527978cfe.png">
5. あとはEnter連打してれば成功するはず
![スクリーンショット 2020-10-25 16.53.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26446/d83b9ea8-fd2d-bd79-3bf8-71bb4c56576f.png)

## FirebaseのiOSアプリ用の設定
* 認証用のファイルをダウンロードして`ios/Runner`のフォルダに設置する作業をせねばならない。
* ブラウザからやっても良いが、コマンドラインでもできる

```shell
$ pwd
~/git/hogeApp/firebase

$ firebase apps:create IOS -b ${YOUR_DOMAIN}.${APP_NAME} ${APP_NAME}
$ firebase apps:sdkconfig IOS > ../${APP_NAME}/ios/Runner/GoogleService-Info.plist
```

* 次にXcodeを開いて、Runnerフォルダから「Add Files to "Runnter"」を選び、GoogleService-Info.plistを追加
  * ブラウザのダウンロードエリアから直接D&Dするとコピーされないので注意
<img width="480" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26446/4a2bd190-1296-5c5a-bde3-4fa54fc91a6b.png">
 
## FirebaseのAndroidアプリの向けの設定

### google-services.jsonの設置

```shell
$ firebase apps:create ANDROID -a ${YOUR_DOMAIN}.${APP_NAME} ${APP_NAME}
$ firebase apps:sdkconfig ANDROID > ../${APP_NAME}/android/app/google-services.json
```

### SHA1とSHA256をFirebaseアプリに登録する

* ~~注: `Firebase Authentication`を使用しないなら以下の手順は不要だが、全裸セキュリティでFirestore使うことはまずありえないので...~~
* 上記は微妙にうそっぱちで、Firebase Authのうち、GoogleID認証と電話番号認証を使う場合のみ必要のようです。匿名認証だけなら不要。
 
```shell
# App IDを調べる
$ pwd
~/git/hogeApp/firebase

$ firebase apps:list
✔ Preparing the list of your Firebase ANDROID apps
┌──────────────────┬───────────────────────────────────────────────┬──────────┐
│ App Display Name │ App ID                                        │ Platform │
├──────────────────┼───────────────────────────────────────────────┼──────────┤
│ [Not specified]  │ 1:1234567890:android:123456789abcdefxxxxxxxxg │ ANDROID  │
└──────────────────┴───────────────────────────────────────────────┴──────────┘

# ↑のApp IDをコピー

# SHA1/SHA256を取得
$ cd ../${APP_NAME}/android
$ ./gradlew signingReport

> Task :app:signingReport
...
SHA1: 11:22:33:44:55:66:77:88:99:00:AA:BB:CC:DD:EE:FF:11:22:33:44
SHA-256: 11:22:33:44:55:66:77:88:99:00:AA:BB:CC:DD:EE:FF:11:22:33:44:55:66:77:88:99:00:AA:BB:CC
...

### SHA1/SHA256の登録

$ cd ../../firebase/

# SHA1例: 
# firebase apps:android:sha:create 1:1234567890:android:123456789abcdefxxxxxxxxg 11:22:33:44:55:66:77:88:99:00:AA:BB:CC:DD:EE:FF:11:22:33:44

$ firebase apps:android:sha:create {APP_ID} {SHA1鍵}

# SHA256例: 
# firebase apps:android:sha:create 1:1234567890:android:123456789abcdefxxxxxxxxg 11:22:33:44:55:66:77:88:99:00:AA:BB:CC:DD:EE:FF:11:22:33:44:55:66:77:88:99:00:AA:BB:CC

$ firebase apps:android:sha:create {APP_ID} {SHA256鍵}

# 鍵の種類は勝手に認識するのでオプション等は不要

# 登録されたか確認
$ firebase apps:android:sha:list 1:1234567890:android:123456789abcdefxxxxxxxxg
```

### ${APP_NAME}/android/build.gradle を書き換え
```gradle
buildscript {
    ...
    
    dependencies {
        ...
        // 追加
        classpath 'com.google.gms:google-services:4.3.4'
    }
}
```


### ${APP_NAME}/android/app/build.gradle を書き換え
```gradle
// 追加
apply plugin: 'com.google.gms.google-services'

android {
    ...
    defaultConfig {
        ...
        // 追加(忘れるとAndoridのコンパイルでコケる）
        multiDexEnabled true
    }
}

dependencies {
    ...
    // 追加（Analyticsいらないならいらないかも？）
    implementation platform('com.google.firebase:firebase-bom:25.12.0')
}

```

## pubspec.yaml に追記

### ${APP_NAME}/pubspec.yaml
```yaml
dependencies:
  # 追加
  firebase_core: 
  firebase_auth:
  cloud_firestore:
```

## main.dartに追記

```dart
// firebase_coreをimportする
import 'package:firebase_core/firebase_core.dart';

// mainをasyncにしてしまう
Future<void> main() async {

  // 2行追記
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();

  // とりあえずFirebaseAuthに
  await FirebaseAuth.instance.signInAnonymously();

  // とりあえずFirestoreへ書き込んで見るテストコード
  await FirebaseFirestore.instance.collection('users').add({'hoge': 'piyo'});

  runApp(MyApp());
}
```

## できた！

![スクリーンショット 2020-10-25 18.09.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26446/2fbac932-835b-35d0-4429-6360b4e46ff4.png)

# まとめ
* 全然爆速じゃないんだよなぁ...🤔