概要
Flutter と Firebase を連携し、Firestore へデータを書き込む。
Firebase との連携は涙を流しながらマニュアルで行った。
ブログ内でキーや ID を容赦なくスクショで晒しているが、本来はダメ。自分は検証完了したら削除してる。
環境
- Flutter 2.10.2
- firebase_core 1.13.1
- cloud_firestore 3.1.10
- iPhone SE (2nd generation) シミュレータ
チュートリアル
Flutter プロジェクト作成
Org (組織) を指定し、Flutter プロジェクト作成。
BundleID の指定と勘違いしていたので firestoreManual はいらんかった。
flutter create firebase_manual --org com.runble1.firestoreManual cd firebase_manual
プラグインを追加。
flutter pub add firebase_core flutter pub add cloud_firestore
iOS の利用バージョンを上げておく。
vi Podfile
# platform :ios, '9.0'
platform :ios, '10.12'
Firebase プロジェクト準備
コンソールから手動で作る。
Firebase へ iOS アプリ登録
プロジェクト設定 → 全般 → マイアプリ → Apple アプリ → アプリを追加 を選択(激闘の跡が見える)。
![](https://storage.googleapis.com/stateless.yaruzo-eigo.com/2022/02/e28af0fd-スクリーンショット-2022-02-26-14.52.25-1024x292.png)
BundleID (アプリを一意に識別するもの) を入れる必要がある。
Flutter アプリでは、以下に記述されている。
ios/Runner.xcodeproj/project.pbxproj
ファイル内PRODUCT_BUNDLE_IDENTIFIER
の値
今回は指定した com.example.firestoreManual という IDを Firebase へ登録する。
(flutter create 時に何も指定しないと com.example.プロジェクト名 となる。)
![](https://storage.googleapis.com/stateless.yaruzo-eigo.com/2022/02/4ef95630-スクリーンショット-2022-02-26-13.48.22-934x1024.png)
ここ以外は全部次へでいい。
アプリが登録できたことを確認。
GoogleService-Info.plist をダウンロードしておく。
![](https://storage.googleapis.com/stateless.yaruzo-eigo.com/2022/02/60864a4c-スクリーンショット-2022-02-26-15.04.26-1024x599.png)
鬼門 : Firebase 構成ファイルを Flutter プロジェクトに追加
鬼門。
ダウンロードした GoogleService-Info.plist を Flutter プロジェクトに追加する。
公式ドキュメントには Xcode 使って移動しよろ、と書いてある。いやわかんねえよw
Xcode を使用して、Flutter アプリの
Flutter アプリに Firebase を追加するRunner/Runner
ディレクトリにファイルを移動します。
Xcode をコンソールで開く方法。
cd ios
xed .
Finder で GoogleService-Info.plist があるフォルダを開き、以下の Xcode の Runner/Runnber ディレクトリへドロップアンドドロップで移動させた。
![](https://storage.googleapis.com/stateless.yaruzo-eigo.com/2022/02/9d8e5551-スクリーンショット-2022-02-26-15.54.14-1024x331.png)
追加時にコンソール出るので Finish 。
![](https://storage.googleapis.com/stateless.yaruzo-eigo.com/2022/02/c0ab3253-スクリーンショット-2022-02-26-15.53.48-1024x602.png)
Firesote データベース作成
Firestore データベースを作成する。
Firebase コンソールの左サイドバーから「Firestore Database」。
![](https://storage.googleapis.com/stateless.yaruzo-eigo.com/2022/02/9930d2d0-スクリーンショット-2022-02-27-10.43.14.png)
「データベースの作成」をクリック。
![](https://storage.googleapis.com/stateless.yaruzo-eigo.com/2022/02/7f025976-スクリーンショット-2022-02-26-20.09.05-1024x359.png)
テストモードで作成する。
本番モードはこんな記事を見ているやつにはまだ早い。
![](https://storage.googleapis.com/stateless.yaruzo-eigo.com/2022/02/a7cd1c64-スクリーンショット-2022-02-26-20.09.38-1024x708.png)
「+コレクションを開始」より users コレクション作成。
![](https://storage.googleapis.com/stateless.yaruzo-eigo.com/2022/02/f2496a6a-スクリーンショット-2022-02-26-20.12.27-1021x1024.png)
データベースの作成完了。
データ追加のサンプルアプリ
カウンターアプリを改造し、Floating Action Button を押した場合、 users コレクションにデータが追加されるサンプル。汚いのは許して。
vi lib/main.dart
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Firestore Add Sample',
home: FirestoreSave(),
);
}
}
class FirestoreSave extends StatefulWidget {
@override
_MyFirestorePageState createState() => _MyFirestorePageState();
}
class _MyFirestorePageState extends State<FirestoreSave> {
@override
Widget build(BuildContext context) {
CollectionReference users = FirebaseFirestore.instance.collection('users');
Future<void> addFirestoreUser() {
// Call the user's CollectionReference to add a new user
return users
.add({
'full_name': "fullName",
'company': "company",
'age': "age"
})
.then((value) => print("User Added"))
.catchError((error) => print("Failed to add user: $error"));
}
return Scaffold(
appBar: AppBar(
title: Text("title"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'Body'
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: addFirestoreUser,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
起動・確認
Flutter アプリを起動。
flutter run
いつもの画面が表示されるので、右下の Floating Action Button を押す。
![](https://storage.googleapis.com/stateless.yaruzo-eigo.com/2022/02/6a18d064-スクリーンショット-2022-02-27-10.36.01-502x1024.png)
コンソールには「flutter: User Added」と刻まれる。
![](https://storage.googleapis.com/stateless.yaruzo-eigo.com/2022/02/c681ed23-スクリーンショット-2022-02-27-10.38.10-1024x151.png)
Firestore コンソールからもデータが追加されたことを確認!
![](https://storage.googleapis.com/stateless.yaruzo-eigo.com/2022/02/13d5ee09-スクリーンショット-2022-02-27-10.35.38-1024x392.png)
まとめ
泣きながらコンソールより手動で Flutter Firebase 連携を行った。
次回は FlutterFire CLI からやる。
また、Firestore も本番モードへ移行していく。
エラー
FirebaseException ([core/not-initialized] Firebase has not been correctly initialized.
Firebase が正しく初期化されていないとエラー。
Exception has occurred.
FirebaseException ([core/not-initialized] Firebase has not been correctly initialized.
Usually this means you've attempted to use a Firebase service before calling `Firebase.initializeApp`.
View the documentation for more information: https://firebase.flutter.dev/docs/overview#initialization
)
Xcode を利用しないで GoogleService-Info.plist を ios/Runner に移動した際に発生。
(気合を入れて) Xcode で移動させた後に出なくなった。(Firebase情報が認識されてなかった?)。
flutter: Failed to add user: [cloud_firestore/permission-denied] The caller does not have permission to execute the specified operation.
Firestore へのアクセス権がないパーミッションエラー。
Firestore を本番モードで作成した場合、セキュリティルールは下記となっている。
- 全ての read, write を拒否する
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false;
}
}
}
テストモードで作った場合のセキュリティルールに変更しておく。
- 2022年3月28日(作成から1ヶ月後)まで read, write 無制限
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if
request.time < timestamp.date(2022, 3, 28);
}
}
}
本番モードの Firestore へアクセスできない
認証ユーザ必須の場合でアクセスするセキュリティルールが下記。
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth != null;
}
}
}
Firebase と連携した Flutter からならアクセスできると思っていた。できなかった。
テストモードから本番モードへ移行するのが今後の課題。
参考
![](https://runble1.com/wp-content/uploads/cocoon-resources/blog-card-cache/ff0855456d2985ad0e8833fbe3d135ee.png)
![](https://qiita-user-contents.imgix.net/https%3A%2F%2Fcdn.qiita.com%2Fassets%2Fpublic%2Farticle-ogp-background-9f5428127621718a910c8b63951390ad.png?ixlib=rb-4.0.0&w=1200&mark64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTkxNiZoPTMzNiZ0eHQ9RmlyZXN0b3JlJTIwU2VjdXJpdHklMjBSdWxlcyUyMCVFMyU4MSVBRSVFNiU5QiVCOCVFMyU4MSU4RCVFNiU5NiVCOSVFMyU4MSVBOCVFNSVBRSU4OCVFMyU4MiU4QiVFMyU4MSVCOSVFMyU4MSU4RCVFNSU4RSU5RiVFNSU4OSU4NyZ0eHQtY29sb3I9JTIzMjEyMTIxJnR4dC1mb250PUhpcmFnaW5vJTIwU2FucyUyMFc2JnR4dC1zaXplPTU2JnR4dC1jbGlwPWVsbGlwc2lzJnR4dC1hbGlnbj1sZWZ0JTJDdG9wJnM9MTdiYzAzN2I4NjNjM2ZhM2ZhNjllNTg3ZTllOTAzMTg&mark-x=142&mark-y=112&blend64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTYxNiZ0eHQ9JTQwS29zdWtlU2FpZ3VzYSZ0eHQtY29sb3I9JTIzMjEyMTIxJnR4dC1mb250PUhpcmFnaW5vJTIwU2FucyUyMFc2JnR4dC1zaXplPTM2JnR4dC1hbGlnbj1sZWZ0JTJDdG9wJnM9ZTYyNTFlYzlhMGY3ZmM2ZGZjMDUwNzc3MmVkMzU4N2Q&blend-x=142&blend-y=491&blend-mode=normal&s=1d84db57cf1476bea5bdde918831dd30)
コメント