[Flutter] Firestore を導入する方法のまとめ (Android)

[Flutter] Firestore を導入する方法のまとめ (Android)

Flutter と Firestore

Flutter は Google が中心になって開発が進められているオープンソースのクロスプラットフォームに対応したモバイルアプリケーションフレームワークです。

1ソースでお手軽に iOS, Android のアプリをビルドすることができ、とっても素晴らしいフレームワークです。

Google謹製ということで、もちろん同じく Google が運営しているクラウドサービス Firebase とも連携できます。ここでは Flutter アプリに Firebase の中の1サービス Firestore を連携させる方法をまとめます。

サンプルアプリ

サンプルとして作るのは、Firestore 上の collection を一覧で表示する画面です。ボタンを押すとデータが追加され、その追加したデータが即座に反映されます。

では早速作っていきます。

まずは Flutter プロジェクトを作成します。

Flutter プロジェクトを作成する

$ flutter create flutter-firestore-sample

プロジェクト名を flutter_firestore_sample として適当なディレクトリで作成します。とりあえず生成したままで、後で中身を作ります。

次に Firebaseのプロジェクトを作成して必要な設定を行います。

Firebase のプロジェクト設定

Flutter アプリに Firebase を追加する | Firebase

上のページを参考にしています。

Firebase コンソール を開き、新しくプロジェクトを作成します。

プロジェクト名を “flutter-firestore-sample” にし、ロケーションを東京にしています。これでプロジェクトを作成しましょう。

完了したらしたら次に進みます。

Android アプリ設定

Android のアイコンをクリックして Android アプリに Firebase を追加できるように設定していきます。

パッケージ名

まずはパッケージ名を入力します。パッケージ名には Android のアプリケーションIDを入力します。flutter プロジェクト内の android/app/build.gradle ファイルに設定される applicationId です。

今回は com.sample.flutter_firestore としました。この値を android/app/build.gradle ファイルに設定します。


android {
    // ..
    defaultConfig {
        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
        applicationId "com.sample.flutter_firestore" // ←をパッケージ名に合わせる
        // ..
    }
    // ..
}

上記の通り android/app/build.gradle の内容を修正してください。修正点は applicationId のみです。

デバッグ用の署名証明書 SHA-1

Auth で Dynamic Links、Invites、Google ログイン、電話番号をサポートするために必須です。[設定] で SHA-1 を編集してください。

注: SHA-1 情報は Google ログインと Firebase Dynamic Links で必要です。

上記のような注意書きがありますが、書いてある通り Firestore のみを利用する場合にはこの SHA-1 情報は不要なのでとりあえず設定せずに進みます。設定したい場合は以下のページの手順で keytool を使って生成し、コピペしてください。

Authenticating Your Client | Google APIs for Android | Google Developers

では次に進みます。

google-services.json ファイルをダウンロード

ダウンロードボタンから google-services.json ファイルをダウンロードしてください。画像にある通りにプロジェクトにコピーしないといけません。

上記箇所にダウンロードしたファイルをコピペします。このファイル自体は後からでもダウンロード可能です。

Firebase SDK の追加

次は Firebase SDK の追加ですが、これを画面のサンプルのバージョンに合わせるとまずそうです。というのも以下のページには次のような注意書きがあります。

Flutter アプリに Firebase を追加する | Firebase

注: Flutter は現在、バージョン 3.2.1 の Google サービス プラグインと互換性があります。

ということで念のため Flutter のページにあるバージョンに合わせて追加します。追記するのは2ファイルあり、両方ともファイル名が build.gradle なので混同しないように注意しましょう。

android直下とandroid/app直下にそれぞれ build.gradle という名前でファイルがあります。それぞれを以下のように行を追加してください。

android/build.gradle

buildscript {
  // ...
  dependencies {
    // ...
    // 以下の行を追加してください。
    classpath 'com.google.gms:google-services:3.2.1'  // Google Services plugin
  }
}
allprojects {
  // ...
  repositories {
    // 以下の行が存在しなければ追加してください。
    google()  // Google's Maven repository
    // ...
  }
}

android/app/build.gradle

dependencies {
  // ...
}

// ...

// 最終行に以下の行を追加してください。
apply plugin: 'com.google.gms.google-services'  // Gradle plugin

以上でAndroidアプリにかかわる設定は完了です。Firebase のアプリ設定は次に進んでインストールの確認は[このステップをスキップ]で終了してしまいましょう。

Firebaseのアプリ設定が中途半端になりますがこれでOKです。

Cloud Firestore データベースの作成

データベースを作成します。Firebase Console からプロジェクトを開き、Database のメニューを開きます。データベースを作成するボタンから新しい Firestore Database を作成します。

作成時に Cloud Firestore セキュリティールールの設定をどうするか聞かれるので、[テストモードで開始]を選択しておきます。実運用時にはセキュリティールールをしっかりと設定しましょう。

次にコレクションを作成します。今回は “books” というコレクションを作り、フィールドに “title”, “author” を持たせます。

上のように1件だけデータを作成しました。

Flutter アプリの開発

以下は通常の Flutter アプリの開発を進めていきます。先ほど作成したデータベースに接続し、データを読み込めるようにします。

まずは Firebase を利用するためのプラグインを導入します。

Firebase 関連のプラグインはこちらのページにまとまっています。

今回は Firestore を利用するので以下のプラグインを追加します。

cloud_firestore | Flutter Package

pubspec.yaml

dependencies:
  flutter:
    sdk: flutter

  cloud_firestore: ^0.9.13

pubspec.yaml を更新したら flutter packages get でパッケージを追加します。

画面を作る

import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';

void main() => runApp(MyHomePage());

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  var count = 1;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Firestore Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Firestore Demo'),
        ),
        body: createListView(),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            // Firestore 上にデータを追加
            Firestore.instance.collection('books').add({
              'title': 'タイトル$count',
              'author': '著者$count',
            });
            count += 1;
          },
          child: Icon(Icons.add),
        ),
      ),
    );
  }

  createListView() {
    Firestore.instance.collection('books').snapshots().listen((data) {
      print(data);
    });

    return StreamBuilder(
      stream: Firestore.instance.collection('books').snapshots(),
      builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
        // エラーの場合
        if (snapshot.hasError) {
          return Text('Error: ${snapshot.error}');
        }

        // 通信中の場合
        switch (snapshot.connectionState) {
          case ConnectionState.waiting:
            return Text('Loading ...');
          default:
            return ListView(
              children: snapshot.data.documents.map((DocumentSnapshot document) {
                return new ListTile(
                  title: new Text(document['title']),
                  subtitle: new Text(document['author']),
                );
              }).toList(),
            );
        }
      },
    );
  }
}

Firestore へのアクセスの方法はプラグインのページにいくつか例があります。

上のコードも基本それに倣っています。

簡単に説明すると QuerySnapshot というのが監視できる Firestore のオブジェクトで、上の例だと “books” という collection の変更を監視しています。変更を検知すると、自動で Widget を再構築してくれるのが StreamBuilder です。

StreamBuilder を使うと自分で状態を管理せずとも変更に応じて書き換えが行われるので便利です。エラーや読み込み中の状態も保持しているのでそれぞれに応じた描画が可能です。

以下動かしてみたときのイメージです。後ろでコンソールを直接いじってデータを追加しています。

いい感じに Widget が書き換えられているのがわかります。追加ボタンに応じでデータも追加されます。もちろんクラウド上に追加されたデータは保持されているので、アプリを再起動しても状態が復元されます。

以上、サンプル実装と解説でした。以下、私が実装している途中に遭遇したビルドエラーの対処法をメモして終わります。

ビルドエラー

D8: Cannot fit requested classes in a single dex file (# methods: 71610 > 65536)

このエラーはメソッド数が 65536 を超えるとビルドできないという制約に引っかかったときに発生するものです。自分が作成したメソッドだけでなく利用するライブラリのメソッドも含みます。

今回だと Firebase のライブラリを導入するに当たりこのエラーが発生する可能性があります。

このエラーを突破するには android/app/build.gradle に設定を追加する必要があります。

android/app/build.gradle

android {
    defaultConfig {
        ...
        minSdkVersion 21 
        targetSdkVersion 26
       // ↓これを追加
        multiDexEnabled true
    }
    // ..
}


dependencies {
  // minSdkVersion が 20 以下の場合のみ
  // ↓これを追加
  compile 'com.android.support:multidex:1.0.3'
}

参考URL

Flutterカテゴリの最新記事