- 概要
- 設計
- チュートリアル
- まとめ
- エラー
- FirebaseCommandException: An error occured on the Firebase CLI when attempting to run a command.
- [!] The FlutterFire plugin cloud_firestore for macOS requires a macOS deployment target of 10.12 or later.
- FirebaseException ([core/not-initialized] Firebase has not been correctly initialized.
- _CastError (Null check operator used on a null value)
- 参考
概要
公式ドキュメントにあるサンプルで、Firestore からデータを取得するサンプルを動かす。Firestore 上のデータは手動追加する(アプリから追加する場合)。
(cloud_firestore の公式 Example は複雑すぎた)。
環境
- Flutter 2.10.2
- flutterfire_cli 0.1.1+2
- firebase_core 1.12.0
- cloud_firestore: ^3.1.8
- iPhone SE (2nd generation) シミュレータ
設計
Firestore データ取得
Firestore はドキュメントベース型の NoSQL 。
Collection
の中に複数のDocument
が含まれるDocument
には json 形式のデータを格納
取得する snapshot の種類
DocumentSnapshot
QuerySnapshot
QueryDocumentSnapshot
snapshot を取得するパターン
DocumentReference
を指定し単一Document
を取得Collection
を指定し複数Document
を取得- 「
Query
を使って複数のDocument
を取得するパターン」とも言えます Query
を使うので返却されるsnapshotの型はQueryXxx
となる
- 「
チュートリアル
Firebase CLI 準備
下記参照。
FlutterFire CLI 準備
Flutter プロジェクト作成
Flutter プロジェクト作成。
flutter create firestore_read --org com.runble1.firestoreRead cd firestore_read
firebase_core
を追加。
flutter pub add firebase_core flutter pub add cloud_firestore
iOS 利用バージョンを上げておく。
vi Podfile
# platform :ios, '9.0'
platform :ios, '10.12'
ここで一度起動し、エラーが発生しないことを確認しておくといいぞ。
iOS バージョン上げたせいで起動遅いけど。
flutter run
FlutterFire CLI から Firebase プロジェクト作成
FlutterFire CLI から新規プロジェクトを作成する。
flutterfire configure
create a new project
より、firestore-add プロジェクトを作成する。
- Project 名 : firestore-read-sample
- Platform : ios
i Found 3 Firebase projects.
✔ Select a Firebase project to configure your Flutter application with · <create a new project>
✔ Enter a project id for your new Firebase project (e.g. my-cool-project) · firestore-read-sample
i New Firebase project firestore-read-sample created succesfully.
✔ Which platforms should your configuration support (use arrow keys & space to select)? · ios
i Firebase ios app com.runble1.firestoreRead.firestoreRead is not registered on Firebase project firestore-read-sample.
i Registered a new Firebase ios app on Firebase project firestore-read-sample.
Firebase configuration file lib/firebase_options.dart generated successfully with the following Firebase apps:
Platform Firebase App Id
ios 1:495423162590:ios:f883afab50eb61df499a4f
Learn more about using this file in the FlutterFire documentation:
> https://firebase.flutter.dev/docs/cli
Firebase コンソールからもアプリが連携されたことを確認できる。
(ID は公開しないほうが良い、自分はすぐ消した)
lib/firebase_options.dart
が作成される。
下記のように Firebase へのアクセス情報が記載されている(マスキングした)。
// File generated by FlutterFire CLI.
// ignore_for_file: lines_longer_than_80_chars
import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
import 'package:flutter/foundation.dart'
show defaultTargetPlatform, kIsWeb, TargetPlatform;
/// Default [FirebaseOptions] for use with your Firebase apps.
///
/// Example:
/// ```dart
/// import 'firebase_options.dart';
/// // ...
/// await Firebase.initializeApp(
/// options: DefaultFirebaseOptions.currentPlatform,
/// );
/// ```
class DefaultFirebaseOptions {
static FirebaseOptions get currentPlatform {
if (kIsWeb) {
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for web - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
}
// ignore: missing_enum_constant_in_switch
switch (defaultTargetPlatform) {
case TargetPlatform.android:
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for android - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
case TargetPlatform.iOS:
return ios;
case TargetPlatform.macOS:
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for macos - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
}
throw UnsupportedError(
'DefaultFirebaseOptions are not supported for this platform.',
);
}
static const FirebaseOptions ios = FirebaseOptions(
apiKey: 'aaaa',
appId: '1:1111:bbbb',
messagingSenderId: '2222',
projectId: 'firestore-read-sample',
storageBucket: 'firestore-read-sample.appspot.com',
iosClientId: '3333-fnd0ta0494t9bhnk3i6sp823n4484rdi.apps.googleusercontent.com',
iosBundleId: 'com.runble1.firestoreRead.firestoreRead',
);
}
Firestore 設定
Firebase プロジェクトより左コンソールの Firestore Database を選択。
- データベースを作成
- テストモード(本番モードは次回以降)
- asia-northeast1
users コレクションを作成する。ドキュメントフィールドは下記。
- full_name
- company
このデータをアプリで読み取る。
Firestore サンプル
公式サンプルを参考に、lib/main.dart
を修正。
- Firebase クラスで initializeApp メソッドを呼び出し
- 生成されたオプションを initializeApp メソッドに提供
import 'package:flutter/material.dart';
import 'firebase_options.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Firestore Read Sample',
home: UserListPage(),
);
}
}
class UserListPage extends StatelessWidget {
final Stream<QuerySnapshot> _usersStream = FirebaseFirestore.instance.collection('users').snapshots();
//print(_usersStream);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('ユーザ一覧'),
),
body: Center(
child: StreamBuilder<QuerySnapshot>(
stream: _usersStream,
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
//if (snapshot.hasError) {
// return Text('Something went wrong');
//}
if (snapshot.connectionState == ConnectionState.waiting) {
return Text("Loading");
}
return ListView(
children: snapshot.data!.docs.map((DocumentSnapshot document) {
Map<String, dynamic> data = document.data()! as Map<String, dynamic>;
return ListTile(
title: Text(data['full_name']),
subtitle: Text(data['company']),
);
}).toList(),
);
},
),
),
);
}
}
起動・確認
起動。
flutter run
Firestore からデータが取得できていれば下記スクショのようになる。
まとめ
Firestore からデータを Read できた。
次回はテストモードで作成した Firestore を本番モードにしていく。
コードは Github にアップ。
エラー
FirebaseCommandException: An error occured on the Firebase CLI when attempting to run a command.
FlutterFire CLI から Firebase プロジェクトを作成する際に起きたエラー。
同じ名前(ID)の Firebase プロジェクトがすでに存在するとのこと。
自分の場合は、同じ名前で削除後に作成しよとして遭遇。
i New Firebase project flutter-firestore-runble1 created succesfully.
FirebaseCommandException: An error occured on the Firebase CLI when attempting to run a command.
COMMAND: firebase projects:create flutter-firestore-runble1 --json
ERROR: Failed to create project because there is already a project with ID flutter-firestore-runble1. Please try again with a unique project ID.
[!] The FlutterFire plugin cloud_firestore for macOS requires a macOS deployment target of 10.12 or later.
意図的に 10.12 以上を使うように指定する
vi ios/Podfile
platform :ios, '10.12'
FirebaseException ([core/not-initialized] Firebase has not been correctly initialized.
以下のようなエラーが発生。
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
)
DefaultFirebaseOptions の指定がない書き方をしていた。
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
Firebase
.initializeApp で DefaultFirebaseOptions
を指定するように変更。
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(MyApp());
}
_CastError (Null check operator used on a null value)
null を比較しようとしてエラー。データが取得できてない?
無理やりすすめるとシミュレータ側もエラーが出る。
該当のコード。 snapshot から data を取り出している部分。
children: snapshot.data!.docs.map((DocumentSnapshot document) {
つまりデータ取得ができていなかった。
自分の場合、Firestore を本番モードで作成していたため、セキュリティルールが全拒否となっていたことが原因。
暫定対応として、テストモードのセキュリティルールに上書きした。
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if
request.time < timestamp.date(2022, 3, 29);
}
}
}
じゃあ本番モードでのアクセスどうするの?
コメント