Firebaseを使ってみる(セットアップ編)

2023年5月27日

開発環境
OS:Windows 11
SDK:VS Code + flutter 3.7.5

概要

アプリを作るうえで欠かすことのできない存在であるデータベース。

Firebaseなら簡単、お気軽に利用することができます。

今回はFirebaseのセットアップを行います。

Firebaseでプロジェクトを作成する

Firebaseにアクセスし、プロジェクトを作成します。

無料のSparkプランと有料のBlazeプランがあります。

いつでもBlazeプランに切り替えることができるのでSparkプランから始めるのがいいかもしれません。

プロジェクトを作成したら、利用したい機能を有効にします。

FirestoreやStorageなどのデータベースについてはアクセス制限設定(ルール)が設けられています。

初めはリード、ライトが無効化されているので編集する必要があります。

Firestoreの場合、特定のパス(<some_path>の部分)のリード、ライトを許可するなら、下記のように定義します。

service cloud.firestore {
  match /databases/{database}/documents {
    match /<some_path>/{document=**} {
      allow read, write: if true;
    }
  }
}

Firebaseをセットアップする

ターミナルでFlutterプロジェクトに移動します。

下記コマンドを入力し、Firebase CLIをインストールします。

npm install -g firebase-tools

※Node.jsをインストールしてない場合は先にそちらをインストールします。

インストールが終わったら、下記コマンドでFirebaseにログインします。

(プロジェクトを作成したGoogleアカウントでログインします。)

firebase login

最後にFirebaseの初期化を行います。

firebase init

Firebaseのどの機能を使うかを選択します。

これでセットアップ完了です。

今回は以上です。

今月のみてみて(2023年4月)

Firebase連携アプリ、みてみてエストーク伊勢125社巡り

このうち、みてみてにフォーカスを当て、Firebaseのアクセス動向やアプリの改善を考察する開発記事です。

Realtime Database+Storage構成の投稿アプリ

まずはアプリのユーザー数の変動とともにFirebaseのアクセス動向を確認します。

2023年4月28日~2023年5月27日のユーザー数の変動

(ユーザー数の変動)

1ヶ月の新規獲得ユーザー数

前にアプリの起動処理に修正をかけたところが遅延の原因となっていたようで修正。

それが起因となったわけではないとおもうが、ユーザー数は微増、かつ、IN>OUTの状態。

(インストールの上位国)

このあたりは変動なし。

インドネシアは伸びませんでした。

南アフリカでインストールされたのは新たなトレンドです。

2023年5月27日直近のFirebaseの変動

(Firebaseの変動)

直近のfirebaseの動き
1ヶ月のfirebase使用量

ユーザー数の微増に伴い、ダウンロード容量が増加。

ユーザー数の増加割合に対するダウロード容量の増加分が気になるが、まだ微増すぎて判断しずらい。

2023年4月28日~2023年5月27日のAdMob

今月はAdMob広告収入:103円、 Firebase使用料:0円となりました。

今月のみてみて

(今月の投稿ピックアップ)

投稿ありがとうございます!

プライバシーを考慮してもらっているのか気になりますが。。。

今後の改善案

(未消化の課題)

・アプリUIブラッシュアップの継続

・フレンドグループ化と共有機能の追加

,

ネイティブコードで処理する

2023年4月28日

開発環境
OS:Windows 11
SDK:VS Code + flutter 3.7.5

ネイティブコード

FlutterでAndroid、iOS向けのアプリ開発を行っているとどうしてもDartでは処理できないネイティブコードに依存する処理を実装する場合がでてきます。

そのような場合はどうするか?

Dart側で内部通信処理を実装し、ネイティブコード側で処理をするよう依頼します。

ネイティブコード側は内部通信の受信を行い、依頼に従い、処理を行います。

MethodChannel

内部通信を行うためにMethodChannelを使用します。

例えば、ボタンを押下したときにネイティブコードで処理を行う場合、Dart側では下記のような実装になります。

MethodChannelで使用するチャンネルと通信コードはDart側とネイティブコード側で合わせます。

チャンネル「samplesetting」、通信コード「dispSetting」

import 'package:flutter/services.dart';


    child: ElevatedButton(
        onPressed: () async {
            const MethodChannel channel = MethodChannel('samplesetting');
            await channel.invokeMethod('dispSetting');
        },
    )

それに対し、ネイティブコード側は内部通信の受信を行い、処理を行います。

Androidの場合だと下記のような実装となります。

処理の実装は、プロジェクト作成時に自動生成されたMainActivity.ktで行います。

(プロジェクトフォルダ)\android\app\src\main\kotlin\・・・\MainActivity.kt

import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import kotlinx.coroutines.ExperimentalCoroutinesApi
import androidx.annotation.NonNull
import android.content.Intent
import android.provider.Settings
import android.net.Uri

class MainActivity: FlutterActivity() {
    private val CHANNEL = "samplesetting"

    @OptIn(ExperimentalCoroutinesApi::class)
    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler{
                call, result ->
            if(call.method == "dispSetting"){
                try {
                    val intent = Intent();
                    intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                    intent.setData(Uri.parse("package:com.example.sample"))
                    startActivity(intent);
                    result.success("success");
                } catch (e:Exception) {
                    result.notImplemented()
                }
            }else{
                result.notImplemented()
            }
        }
    }
}

今回は設定画面を表示する処理を実装してみました。

※パッケージ app_settingsをインストールすれば、Dartだけで設定画面を表示することもできます。

動作確認

実機にインストールして動かすと下記のようになりました。

起動時
ボタン押下時

iOSでも同様に内部通信を受信し、ネイティブコードで処理を実行させることができます。

今回は以上です。

モバイルアプリをデバッグする

2023年4月26日

開発環境
OS:Windows 11
SDK:VS Code + flutter 3.7.5

事前準備

モバイルアプリをデバッグする場合、エミュレータか、実機を使います。

実機を使うなら、実機とPCをケーブルでつなげるだけでデバイスが自動で認識され、

デバッグできますが、エミュレータを使う場合はエミュレータ自体を事前に作成しておく必要があります。

Androidの場合だとAndroid Studioを立ち上げ、Deveice Managerでデバイスイメージを作成します。

OSバージョン、端末(スクリーンサイズ)、スペックと選択を進めれば作成できます。

エミュレータでデバッグする

エミュレータの作成が終わったらVSCodeでFlutterプロジェクトを立ち上げます。

デバッグの実行方法は2通りあります。

実行方法1)ボタン操作

まずはエミュレータを選択します。

画面下のバーにあるデバイス表示部をクリックします。

すると先ほど作成したエミュレータの一覧が表示されるようになります。

デバッグで使用したいエミュレータを選択します。

エミュレータを選択したら、デバッグを実行します。

画面左上のデバッグ起動(▷)で「Flutter(対象端末)」を選択し、クリックすればデバッグが起動します。

その2)ターミナルコマンド

まずはターミナルでデバイス一覧を表示します。

flutter device

表示された一覧から対象機種を選び、機種IDを指定してデバッグ起動コマンドを入力します。

flutter run -d (機種ID)

※ターミナルでデバッグ起動した場合はターミナルに「q」を入力して終了します。

デバッグ起動するとエミュレータ内でアプリが起動します。

実機でデバッグする

実機でデバッグする場合は実機とPCをケーブルで接続します。

実機が自動で認識されデバイス一覧に表示されます。

デバッグの起動方法はエミュレータと同様です。

ボタン操作でもターミナルコマンドでもどちらも起動できます。

起動するとスマホの画面上にアプリが表示されます。

メイン画面

今回は以上です。

Riverpodを使ってみる

2023年4月30日

開発環境
OS:Windows 11
SDK:VS Code + flutter 3.7.5

パッケージとは

Flutterで実装するうえでかかせないのがパッケージです。

Flutterのベース機能はUIに特化されているため、アプリの機能性、操作性を拡張させるような実装を行うにはパッケージをインストールする必要があります。

Webを表示させたい、画像を表示させたい、データ管理を行いたい、など、

ベースロジックで対応しきれない場合は、Pub.devから適切なパッケージを探し、インストールします。

今回は状態管理を行うパッケージ、Riverpodを利用してアプリを作ります。

パッケージをインストールする

インストール手順は簡単です。

コマンドプロンプト(ターミナル)でパッケージ(flutter_riverpod)をインストールしたい当該プロジェクトフォルダに移動し、下記コマンドを実行します。

flutter pub add flutter_riverpod

プロジェクトにパッケージがインストールされます。

パッケージはpubspec.yamlで管理されており、yamlファイル内に指定したパッケージが追加されます。

逆にpubspec.yamlにインストールしたいパッケージを追記し、下記コマンドを実行してもパッケージをインストールすることができます。

flutter pub get

実装してみる

flutter create test2で作成したサンプルプログラムをRiverpodで置き換えてみます。

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

final countProvider = StateProvider((ref) => 0);

void main() {
  runApp(const ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends ConsumerWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  void _incrementCounter(WidgetRef ref) {
    ref.read(countProvider.notifier).state++;
  }

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    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(
              ref.watch(countProvider).toString(),
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {_incrementCounter(ref);},
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

まずパッケージを使用するためにパッケージをimportします。

Riverpodを適用するためのポイントは3点です。

1)ProviderScopeで適用範囲とするクラスを指定する

2)StatefulWidget → CunsumerWidget へ置き換える

3)buildの引数にWidgetRefを追加する

あとはStateProviderを定義して参照、更新します。

値を参照する ref.read(定義名).state

値を参照する(更新検知) ref.watch(定義名).state

値を更新する ref.read(定義名.notifier).state = 更新値 

実行すると下記のようになりました。

setStateを使用したサンプルプログラムと同じ動きになります。

またRiverpodの優れた点は別ページに遷移しても変わらず参照できる点です。

下記のようにページ遷移を実装します。

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:test2/pages/nextpage.dart';

final countProvider = StateProvider((ref) => 0);

void main() {
  runApp(const ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends ConsumerWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  void _incrementCounter(WidgetRef ref) {
    ref.read(countProvider.notifier).state++;
  }

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    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(
              ref.watch(countProvider).toString(),
              style: Theme.of(context).textTheme.headlineMedium,
            ),
            ElevatedButton(onPressed: (){Navigator.push(context, MaterialPageRoute(builder: (context) => const NextPage()));}, child: const Text('next'))
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {_incrementCounter(ref);},
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:test2/main.dart';

class NextPage extends ConsumerWidget {
  const NextPage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("next page"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times on Main page:',
            ),
            Text(
              ref.watch(countProvider).toString(),
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),// This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

実行すると下記となります。

メイン画面
次画面

次ページにおいてもメイン画面の値を参照できます。

ちなみに複雑な状態管理を行うにはStateNotifierProviderを使用します。

今回は以上です。

今月のみてみて(2023年3月)

Firebase連携アプリ、みてみてエストーク伊勢125社巡り

このうち、みてみてにフォーカスを当て、Firebaseのアクセス動向やアプリの改善を考察する開発記事です。

Realtime Database+Storage構成の投稿アプリ

まずはアプリのユーザー数の変動とともにFirebaseのアクセス動向を確認します。

2023年3月20日~2023年4月21日のユーザー数の変動

(ユーザー数の変動)

1ヶ月の新規獲得ユーザー数

今月も改修を入れることができなかったのですが、なんとか現状維持です。

(インストールの上位国)

インドネシアが伸びてきました。

と言うよりフィリピンの勢いが落ちてきた結果なのかもしれません。

2023年4月21日直近のFirebaseの変動

(Firebaseの変動)

直近のfirebaseの動き
1ヶ月のfirebase使用量

先月と同様です。

心配することがない使用量です。

2023年3月20日~2023年4月21日のAdMob

今月はAdMob広告収入:73円、 Firebase使用料:0円となりました。

今月のみてみて

(今月の投稿ピックアップ)

投稿ありがとうございます!

今後の改善案

(未消化の課題)

・アプリUIブラッシュアップの継続

・フレンドグループ化と共有機能の追加

(アプリ使用中の気付き)

・投稿機能の改善

,

送迎バスの問題

2023年4月10日

問題はなくならないのか

子供たちの交通手段としてなくてはならない送迎バス。

そんな送迎バスの利用において昨今の問題として挙がっているのが子供の降ろし忘れです。

人が介入する以上、間違いは発生します。

大切なのは間違いが起こらないための取り組みと万が一間違った場合の早期発見。

大掛かりな対策だと車体へのセンサー導入などもあるかもしれません。

ですが、もっと手軽ですぐにできる対策もあるはずです。

例えばチェックシートの運用やダブルチェック、これだけで降車のタイミングで問題が解決します。

ただし、昨今の問題発生の起因となっていたのは要員不足。

ダブルチェック体制が取れない、不慣れな代替要員での送迎。

その点を踏まえた対策が必要なのかもしれません。

セルフチェックする

個人的にもこの問題は気になったのでセルフチェックアプリを作ってみました。

乗車に座席をチェックし、降車後に再度、座席をチェックする。

アプリ自体は外部通信を行わない、単純なセルフチェック機能のみの構成です。

スマホ1台を送迎担当が共有し、セルフチェックシートとして利用することで問題抑止になることを願います。

アプリを拡張するなら、

・通信機能追加による乗車状況の共有

・メール通知機能

・チェックし忘れアラーム機能

などの機能が追加可能であり、より使い勝手がよくなるかもしれません。

モバイルアプリをリリースする

2023年4月8日

開発環境
OS:Windows 11
SDK:VS Code + Flutter 3.7.5

Flutterでモバイルアプリとしてビルドするのに必要な環境

Flutterはモバイルアプリ開発をメインとして使用されるフレームワークです。

Webへのデプロイもできますが、モバイルアプリとしてリリースすることも可能です。

モバイルアプリとしてリリースするためにはAndroid、iOSのビルド環境が別途必要です。

Androidアプリをビルドしたい場合はAndroid Studioを、

iOSアプリをビルドしたい場合はXcodeをインストールする必要があります。

ただし、Xcodeはmacしかインストールできないため、

Flutterの強みであるAndroid、iOSの同時リリースを行えるのはmacだけとなります。

この点においてFlutter開発をする前にPC選びを慎重に行う必要があります。

ビルドする

Androidアプリを作成するためのビルドコマンドは以下となります。

flutter build appbundle

ビルドが完了すると下記にaabファイルが生成されます。

(プロジェクトフォルダ)/build/app/outputs/bundle/release/app-release.aab

また、iOSアプリを作成するためのビルドコマンドは以下です。

flutter build ios

ビルドが完了したあとXcodeでarchiveを行い、ipaファイルを生成します。

ExportOptions.plistを用意しておくと下記コマンドでアーカイブまで実行してくれるようです。(自分は使ったことがありません。

flutter build ipa

今回は以上です。

デプロイしてインターネットで公開する

2023年4月8日

開発環境
OS:Windows 11
SDK:VS Code + flutter 3.7.5

デプロイ=サーバーに配置する

flutter runでローカル環境で動かし、デバッグが完了したらネットに公開します。

手軽にネットに公開するならFirebaseが便利です。

Firebaseにデプロイするまでの流れは以下となります。

1.Firebaseでプロジェクトを作成する

2.Firebase CLIをインストールする

3.Firebaseにログイン、初期化する

4.Firebaseプロジェクトにデプロイする

プロジェクトを作成する

Firebaseにアクセスしたらログインし、デプロイするためのプロジェクトを作成します。

お試しで使うならSparkプラン(無料版)で問題ありません。

プロジェクトを作成したら、Hostingを選択し、「始める」を押下します。

あとはFirebaseプロジェクトのナビゲーションに従います。

初期設定

初期設定としてFirebase CLIのインストール、Firebaseへのログイン、初期化があります。

すべてコマンドプロンプトでコマンド操作で行います。

Flutterプロジェクトのディレクトリに移動してコマンド入力します。

操作コマンド
CLIインストールnpm install -g firebase-tools
Firebaseログインfirebase login
Firebase初期化firebase init
Firebase初期設定コマンド一覧

デプロイする

Firebaseの初期設定が終わったあとはFlutterプロジェクトをビルドしてデプロイします。

まずはFlutterプロジェクトをビルドします。

flutter build web

ビルドが完了したらデプロイします。

firebase deploy –only hosting

これでインターネットに公開されました。

公開アドレスはFirebaseプロジェクトのHostingを選択するとドメインとして表示されます。

今回は以上です。