💡

Flutter x Firebaseの環境構築、そしてFirestore操作の基本

2023/08/14に公開

初めに

今更ながらFlutterでFirebaseの環境構築をしたので備忘録がわりに対応した内容をまとめる
いつからか分からないけど2022年ぐらいから記事がちらほらある"FlutterFire"を使って構築する
初めてFlutter x Firebase触った時にはこんなのなかったような・・・?
便利である

前提条件

  • Androidエミュレータ、iOSシミュレータ、または実機でFlutterを実行できること
  • Googleアカウントを作っていること

実装環境

  • Android Studio 2022.3.1
  • Flutter 3.10 (Dart 3.0.0)
  • Androidエミュレータ Nexus 6 API 33

インストールしたパッケージ

  • firebase_core: ^2.15.0
  • cloud_firestore: ^4.8.4

Firebaseにログインする

プロジェクト上でTerminalを開いて実行する(IDEはなんでもおk)

  1. Firebase CLI をインストールする npm install -g firebase-tools
  2. Firebase CLIにログインする firebase login
  3. "Allow Firebase to collect CLI and Emulator Suite usage and error reporting information?" とか聞かれたらYと入力する
  4. ブラウザ上でログインを求められるのでログインしたいGoogleアカウントでログインする
  5. 以上でログイン完了

Firebaseプロジェクトを作成し、アプリを登録する

  1. FlutterFireをプロジェクトにインストールする dart pub global activate flutterfire_cli
  2. Flutterアプリの構成をFirebaseに登録する flutterfire configure
  3. プロジェクトを聞かれるので、まだプロジェクトを作っていない場合は "<create a new project> " を選択する
  4. プロジェクト名を聞かれるので、Firebaseの命名規則に従った名前をつける
4~30 文字(半角)の範囲で指定する
文字、数字、スペース、記号(- ' " !)のみを使用する
アルファベットのみを使用する
  1. プラットフォームを聞かれるので自分が作りたいアプリのプラットフォームを選択する。自分は今回適当なので全て選択
  2. "The files android/build.gradle & android/app/build.gradle will be updated to apply Firebase configuration and gradle build plugins. Do you want to continue?" と聞かれるので、そのままエンター
  3. 自分の場合は "`require': cannot load such file -- xcodeproj" とエラーが発生した。単純に "xcodeproj" をインストールする gem install xcodeproj --user-install
    再度、flutterfire configureを実行
  4. Firebase コンソールに接続して、作成したプロジェクトが存在していることを確認
  5. アプリのソースを確認し、"firebase_options.dart" が追加されていること、その他各プラットフォームの設定ファイルが追加されていることを確認(ここがめちゃくちゃ楽)

FireStoreを有効にする

  1. Firebase コンソールの作成したプロジェクトを選択する
  2. 左メニューの「プロダクトのカテゴリ」 -> 「構築」 -> 「Firestore Database」 を選択する
  3. "Cloud Firestore" の「データベースの作成」を選択
  4. Firestoreで開始するモードを選択する。説明は以下。とりあえずFirestoreの参照・更新がしたいので開発環境モードにする(忘れずにセキュリティルールは変える)
    • 本番環境モード: 基本的に外部(今回はアプリ)からの接続は拒絶する。許可したい場合はセキュリティルールの変更が必要
    • 開発環境モード: 外部(今回はアプリ)からの接続を全て許可するが、30日間の制限をつける。30日後以降はセキュリティルールの変更が必要
  5. ロケーションを選択する。
    この記事を見てる人は国内にいると思うので、asia-northeast1asia-northeast2を選択
  6. 「有効にする」押下でFirestoreが有効になり、以下のような画面が表示されるようになる

FlutterアプリでFirestoreを使えるようにする

  1. Firebaseのプラグインをアプリに追加する flutter pub add firebase_core
  2. main.dartに以下のソースを追加し、パッケージをimportする
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';
  1. main.dartmain() 内でFirebaseの初期化のロジックを追加する
Future<void> main() async { // 非同期にする
  // 追加
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  //
  runApp(
    const MyApp(),
  );
}
  1. Androidエミュレータでアプリを起動するともしかしたら以下のエラーになるかもしれない。その場合は、android/build.gradleclasspath 'com.google.gms:google-services:4.3.10'classpath 'com.google.gms:google-services:4.3.14'に変更する
    https://zenn.dev/welchi/articles/flutter-3101-firebase-error
* What went wrong:
Execution failed for task ':app:mapDebugSourceSetPaths'.
> Error while evaluating property 'extraGeneratedResDir' of task ':app:mapDebugSourceSetPaths'
   > Failed to calculate the value of task ':app:mapDebugSourceSetPaths' property 'extraGeneratedResDir'.
      > Querying the mapped value of provider(java.util.Set) before task ':app:processDebugGoogleServices' has completed is not supported

Firestore操作

今回はアプリにボタンを配置して、ボタン上で追加、参照、更新、削除ができるようにする

  1. Firestore操作のためのパッケージを追加する flutter pub add cloud_firestore
  2. 以下エラーが発生する場合は android/app/build.gradle のminSdkVersionを変更する(自分の場合は23にしておいた)
* What went wrong:
Execution failed for task ':app:processDebugMainManifest'.
> Manifest merger failed : uses-sdk:minSdkVersion 16 cannot be smaller than version 19 declared in library [:cloud_firestore] /Users/susaki/GitHub/image_upload/build/cloud_firestore/intermediates/merged_manifest/debug/AndroidManifest.xml as the library might be using APIs not available in 16
  	Suggestion: use a compatible library with a minSdk of at most 16,
  		or increase this project's minSdk version to at least 19,
  		or use tools:overrideLibrary="io.flutter.plugins.firebase.firestore" to force usage (may lead to runtime failures)

Add: 登録

users というコレクションにドキュメントを追加する
users が存在しない場合は自動で作成される
この場合、ドキュメントのIDは自動採番される

ElevatedButton(
  onPressed: () async => {
    await FirebaseFirestore.instance.collection('users').add({'name': 'hoge'})
  },
  child: const Text('Userを追加(Add)'))

うまく追加できない場合

大抵セキュリティルールのせいだと思うので、セキュリティルールを見直す
今回は開発環境モードにしているが、基本的にコレクションやドキュメントの追加や削除、更新をする場合は都度セキュリティルールを設定してあげる必要がある

Update: 更新

指定したIDの値を更新する
Setの更新との違いは、Updateは指定した要素のみ(この場合name)のみ更新するが、setは指定の無い要素は削除してしまう

ElevatedButton(
  onPressed: () async => {
    await FirebaseFirestore.instance
      .collection('users')
      .doc('1OYUhzyUbtAyq6Xaf6an')
      .update({'name': 'hogehoge'})
  },
  child: const Text('Userを更新(Update)'))

Set: 登録、更新

setの場合はIDを指定して登録できる
更新も同様のロジックで更新できるが、前述した通り更新するというよりは作り替えるため、指定したIDで指定した要素で上書きするというイメージである

ElevatedButton(
  onPressed: () async {
    await FirebaseFirestore.instance
      .collection('users')
      .doc('hogehogehoge')
      .set({'name': 'hoge'});
  },
  child: const Text('Userを追加(Set)'))

Delete: 削除

deleteは指定したドキュメントを削除するだけである

ElevatedButton(
  onPressed: () async {
    await FirebaseFirestore.instance.collection('users').doc('hogehogehoge').delete();
  },
  child: const Text('Userを削除(Delete)'))

まとめ

Flutterを使ったFirebaseで開発環境を構築し、実際に動かすコードを簡単にまとめた
今はただインスタンスを呼び出してドキュメント名やそのIDを直で指定して操作する動きになるが、これらの動きをメソッド化して簡単に呼び出せるようにして初めて使い物になるのかなと思う

Discussion