【Flutter】iOS/Android/WebでFirebase Firestoreを使えるようにする。

# はじめに
昨年後半よりFlutter入門して社内用アプリを作っています。
今回はFirebaseのFirestoreを使えるようにします。

# 更新履歴
2021.2.11 初回投稿
2021.2.18 iOS/Android設定時の注意点を追記
2021.5.6 Flutterアップデートに伴い、環境、準備、pubspec等を修正
2022.7.12 Flutter3.0.4に対応

# 環境
[✓] Flutter (Channel stable, 3.0.4, on macOS 12.4 21F79 darwin-x64, locale
ja-JP)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[✓] Xcode - develop for iOS and macOS (Xcode 13.4.1)
[✓] Chrome - develop for the web
[✓] Android Studio (version 4.2)
[✓] VS Code (version 1.69.0)

# 参考にしたサイト

- [Cloud Firestore を使ってみる  |  Firebase](https://firebase.google.com/docs/firestore/quickstart?hl=ja#java)
- [FlutterでFirebaseを使ってみる〜投票アプリ〜 - Qiita](https://qiita.com/121a/items/ee488298a5b9468c3b57)
- [flutter プロジェクトに cloud_firestore を追加するとエラー発生 | 株式会社TKS2](https://tks2.co.jp/2020/03/03/flutter-cloud-firestore-error/)
- [【Flutter】「No Firebase App '[DEFAULT]' has been created - call Firebase.initializeApp() occurred in Instance of xxx 」が発生しFirestoreに接続できない](https://qiita.com/tsuruken/items/96ec39d1bfb4e27fcc6b)


# 準備
~~- FlutterのChannelをbetaにしておく(Web非対応の場合は不要)~~
Flutter2.0から不要になりました。stableのままでWebを使えるようになりました。
(2021.5.6追記)
~~- null safetyにしないと怒られるので、pubspec.yamlのsdkを以下のように変更~~
以下も3.0なら変更不要
```pubspec.yaml
environment:
  sdk: ">=2.17.5 <3.0.0"
```

# やりたいこと

- iOSでもAndroidでもWebでもFirebase Firestoreを使いたい


# 実装手順

## Web
1. パッケージインストール
   pubspec.yamlのdependenciesにfirebaseを追加(最新バージョンは以下を確認)

https://pub.dev/packages/firebase_core

https://pub.dev/packages/cloud_firestore
  
(2021.5.6 バージョンを変更)
(2021.7.31 バージョンを変更)
(2023.7.12 バージョンを変更)

```pubspec.yaml
dependencies:
  firebase_core: ^1.19.1
  cloud_firestore: ^3.2.1
```

2.Web設定
/web/index.htmlにアプリ設定を追加する
(2021.5.6 firebasejsのバージョンを変更)

```/web/index.html
<script src="https://www.gstatic.com/firebasejs/8.5.0/firebase-app.js"></script>
  <script src="https://www.gstatic.com/firebasejs/8.5.0/firebase-firestore.js"></script>
  <script>
    // Your web app's Firebase configuration
    var firebaseConfig = {
      apiKey: "Your apiKey",
      authDomain: "Your authDomain",
      projectId: "Your projectId",
      storageBucket: "Your storageBucket",
      messagingSenderId: "Your messagingSenderId",
      appId: "Your appId"
    };
    // Initialize Firebase
    firebase.initializeApp(firebaseConfig);
  </script>
<script  src="main.dart.js"  type="application/javascript"></script>←この上に記述
```

3.テストFlutter実装

とりあえず、FABを押したら、sampleコレクションにデータを追加するように実装

```lib/main.dart
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';

//import 'dart:async';(不要になりました)

// ignore: non_constant_identifier_names

void main() async {
  WidgetsFlutterBinding.ensureInitialized();//←Firebaseを初期化する際に必要らしい
  await Firebase.initializeApp();//←Firebaseを初期化
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'テストアプリ',
      home: MainScreen(),
    );
  }
}

class MainScreen extends StatelessWidget {
  const MainScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('sample'),
      ),
      floatingActionButton: FloatingActionButton(
        backgroundColor: Colors.indigo,
        onPressed: () {},
        child: IconButton(
          icon: const Icon(Icons.add),
          color: Colors.white,
          onPressed: () {
            debugPrint("test");
            FirebaseFirestore.instance.collection('sample').add(
              {'name': 'test'},
            );
          },
        ),
      ),
    );
  }
}
```

## iOS設定
(注意) 
iosフォルダを開いて、ios/Runner/Runnner.xcworkspaceをXcodeで開いてから設定する

1. Firebaseのプロジェクト設定よりiOSアプリを追加し、Google-Service-info.plistをダウンロード
2. Google-Service-info.plistを/iOS/Runner/に入れる
3. /iOS/Runner/Podfileに記載されている以下の行をコメントアウトを外す

```
#platform :ios, '9.0'
```
4.「9.0」を「12.0」に変更する

```
platform :ios, '12.0'
```
### エラー対応(2022.7.12追記)
2022年7月現在、Flutter3.0.4、cloud_firestore Ver.3.2.1で、iOSシミュレータで起動時は問題ないですが、「flutter build ios --release」すると、エラーが出ます。
直し方は以下を参考にしてください。

https://qiita.com/yoshikoba/items/03b29f5f9a46d0096e52


## Android設定
(注意) 
 - AndroidフォルダをAndroidStudioで開いてから設定する。
 - build.gradleは必ず編集後、sync nowボタンを押す

1. Firebaseでアプリ設定する
  パッケージ名を入力。
  ※パッケージ名はFlutter projectを作成した時のもの。
  ex)com.example.babynames
  忘れた場合、android/app/src/main/AndroidManifest.xmlの一番上の方に記載されている。

2. ※ Google sign-inを使いたい場合、
　デバッグ用の署名証明書 SHA-1も入力しておく必要がある。
　ターミナルで下記のコマンドを実行するとSHA1を取得できるので、コピーして入力する。
　入力するとパスワードを聞かれるが、初期パスワードは「android」

```
keytool -list -v -alias androiddebugkey -keystore ~/.android/debug.keystore
```

3.アプリを登録したら、google-services.jsonをダウンロードして、google-services.jsonをプロジェクトのandroid/app配下に配置
(Android Studioを開き、android/appの部分にドラッグ&ドロップでOK)

4.「android/app/build.gradle」に以下のように追記する

```
---略---
    defaultConfig {
        ---略---
     // defaultConfig内に下記の一行を追加
        multiDexEnabled true
    }
    ---略---
dependencies {
    // dependencies内に下記の一行を追加
    implementation 'com.google.firebase:firebase-firestore:22.0.1'
 }

// ファイルの一番下に下記の一行を追加
apply plugin: 'com.google.gms.google-services' 

```

5.「android/build.gradle」に以下のように追加する

```
buildscript {
 ---略---
    dependencies {
         ---略---
        // 下記の文言を追加
        classpath 'com.google.gms:google-services:4.3.3'
    }
}
```

以上