Flutter×Firebaseで開発をする上で役立ちそうな内容をまとめた。
随時更新予定。
Flutter設定(全般)
パッケージ名の指定
--org
オプションを指定することでパッケージ名を指定することができる。
デフォルトだとcom.example.{アプリ名}
という形で生成されてしまう。
もちろん後で書換えることも可能だが、パッケージ名が予め決まっているならプロジェクト作成時に指定するのが一番手間が少なくて良い。
flutter create --org com.hayapenguin piyopiyo
デフォルトの漢字フォントを変更する
デフォルトだと漢字が中華フォントで表示されてしまうので、日本語ローケルを設定する。
MaterialApp
のsupportedLocales
プロパティにLocale('ja')
を指定する。
import 'package:flutter_localizations/flutter_localizations.dart';
return MaterialApp(
debugShowCheckedModeBanner: false,
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: const [Locale('ja')],
...
);
ref: https://flutter.dev/docs/development/accessibility-and-localization/internationalization
良くわからないエラーが出たらとりあえずHot Restart
思考停止再起動が上手くいくのと同じ感じのノリ。
おそらくHot reloadだとWidgetが変に残っててそれが悪さをしてエラーになる場合がある。
Flutter設定(Android)
デバッグ用の署名証明書 SHA-1, SHA-256を取得する
keytool -list -v \
-alias androiddebugkey -keystore ~/.android/debug.keystore
要求されるパスワードはデフォルトだとandroid
ref: https://developers.google.com/android/guides/client-auth
Widgetの使い方
Buttonをdisabledにする
onPressed
プロパティに渡す関数をnullにする。
別途disabledプロパティ的なものがあれば嬉しいが、ないので三項演算子を使うことになる。
return ElevatedButton(
child: const Text('ボタン'),
onPressed: isValid ? doSomething : null,
)
ref: https://api.flutter.dev/flutter/material/TextButton-class.html
If the onPressed and onLongPress callbacks are null, then this button will be disabled, it will not react to touch.
TextFieldに入力文字数を表示しない方法
TextFieldにmaxLength
プロパティを指定するとテキストの最大入力文字数を指定することができる。その場合、テキストフィールドの右下に現在の入力文字数が表示されるが、隠したいときの方法。
他の入力制限と組み合わせるも考えるとinputFormatters
を使うのが良いと思う。
InputDecoratioin
のcounterText
プロパティに空文字を指定することもできるが、だったらmaxLengthプロパティを使うなって話だし、表示されないだけで表示領域を取ってしまうのでデザイン的にもなし。
return TextFormField(
inputFormatters: [
LengthLimitingTextInputFormatter(12),
],
...
)
Rowの中のTextを折り返す
TextをExpandedで囲んであげる。
ref: https://github.com/flutter/flutter/issues/4128#issuecomment-584347376
Appbarのテキストを真ん中表示にする
centerTitle
プロパティをtrue
にする。 Centerウィジェットを使う方法では中心からずれる。
ref: https://api.flutter.dev/flutter/material/AppBar/centerTitle.html
Widgetの使い分け
TextField vs TextFormField
入力値あをバリデートする必要があるならTextFormFieldを使うと良い。
良くわからなければとりあえずTextFieldを使って、それで機能的に不足する場合にTextFormFieldを使えば良い。
パッケージ
ピン入力のUIを作りたい
SMS認証時のピンコード入力のUIを作成する方法。
もちろん自力でもできるが、pin_input_text_fieldを使うのがおすすめ。
ref: https://pub.dev/packages/pin_input_text_field
Riverpodの使い分け
pub.devにriverpod, flutter_riverpod, hooks_riverpodの3つがある。
Dartのみで使用する場合はriverpod、Flutter Hooksと使うならhooks_riverpodを使用する。
ref: https://riverpod.dev/docs/getting_started
アプリのバージョンを取得したい
package_info
パッケージを使用する。
ref: https://pub.dev/packages/package_info
Firebase(全般)
リージョンの指定
日本向けのサービスの場合は基本的にはasia-northeast1
(東京)でOK。
状況によってはasia-northeast2
(大阪)でも良い。
東京リージョンなら基本的にGCPのほとんどの機能が使えるが、一応以下から使用予定の機能が使えるか確認しておくのが無難。
https://cloud.google.com/about/locations?hl=ja#asia-pacific
Firebase Authentication
SMS認証でピンコードを6桁から変えたい
2021年1月現在の仕様では不可能。
よくあるピンコードの長さは4桁だが、セキュリティ的には長い分には問題ないので敢えて4桁にする必要はない。
ref: https://stackoverflow.com/questions/46141010/can-i-customize-the-firebase-otp-digits-default-6-to-4
SMS認証のテスト時に怪しいと怒られる
こんな感じのエラーメッセージ。
[firebase_auth/too-many-requests] We have blocked all requests from this device due to unusual activity
要は、リクエスト送りすぎ、お前怪しすぎということ。
とはいえ、認証周りの開発時にはどうしてもリクエストを何回も送る必要がある。
Firebaseのコンソール上からテスト用の電話番号と認証コードのセットが用意できるので、開発時はそちらを使用するのがベスト。
Android端末でSMS認証時にアプリが落ちる
Safetynetの設定がない場合、端末の認証のためにブラウザを開こうとするがブラウザがないとアプリが落ちてしまう。
android/app/build.gradle
にブラウザを使用する設定を追加するのがimplementation "androidx.browser:browser:1.3.0"
1つの解決策。
ただ認証コード送信リクエスト時に一度ブラウザが立ち上がるというUX的にはクソな感じになってしまうので普通にSafety Netの設定をするのが無難。
FirebaseのプロジェクトにSHA-256フィンガープリントを追加するのと、GCPコンソールからAndroid Device Verification
のAPIを有効にすると良い。
Firebase Hosting
1つのコードで複数のFirebase Hostingにデプロイしたい
ref: https://stackoverflow.com/questions/63524604/flutter-web-flavor
ref: https://firebase.googleblog.com/2016/07/deploy-to-multiple-environments-with.html
Flutter Web
Flutter Webかどうかを判別する
kIsWeb
定数で判別できる。
ref: https://api.flutter.dev/flutter/foundation/kIsWeb-constant.html
dart.htmlパッケージがAndroid(iOS)だとエラーになる
dart.html
パッケージはWebにしか対応していないみたいで、アプリとしてビルドしようとするとError: Not found: 'dart:html'
と表示されてしまう。
解決策はいくつかあるが、一番簡単なのが、代わりにuniversal_html
を使用すること。
そのままimportするとflutter/material.dart
のWidgetと一部重複してエラーになってしまうので、以下のようにエイリアスをつけて読んであげる。
import 'package:universal_html/html.dart' as html;
ref: https://pub.dev/packages/universal_html
Flutter WebでFirebase SMS認証時に出るreCAPTCHAのWidgetを消したい
2021年1月19日現在ではパッケージのバグでFlutter WebだとreCAPTCHAを非表示にすることができない。
回避策としては、直接DOM操作をしてreCAPTCHAの要素を非表示にする。
final el = window.document.getElementById('__ff-recaptcha-container');
if (el != null) {
el.style.visibility = 'hidden';
}
ref: https://github.com/FirebaseExtended/flutterfire/issues/4377
Textの下部が見切れる
Flutter Web固有の不具合みたいです。一応回避策はあるものの根本的には対応を待つのみです。
ref: https://stackoverflow.com/questions/59672179/flutter-for-web-text-cut-off-at-bottom
URLから#を取り除きたい
url_strategyパッケージを利用する。
ref: https://stackoverflow.com/questions/59870357/how-to-remove-hash-from-url-in-flutter-web
Cloud Functions
Unauthenticatedエラーが出る
GCPのIAMからAllusersに対してCloud Functions Invokerのロールを付与する
firebase-firestore-https-callable-cloud-functions
Unhandled Exception: [firebase_functions/unauthenticated] UNAUTHENTICATED
ref: https://stackoverflow.com/questions/62415509/unauthenticated-error-in-
未分類
TextFieldのフォーカスを外す
ListViewの中にListViewを入れる
freezedでReferenceをプロパティとして持たせたい
そのままだと変換がうまくできないのでJsonConverterを使用する。
ref: https://qiita.com/tetsufe/items/3c7d997f1c13c659628c#comment-5ce93b14ddfbc9ee6428
EnumでString値を取得したい
extenstionを使用する。
ref: https://note.com/hatchoutschool/n/n3a7c6ae218fa
KeyBoardが表示されたときにレンダリングエラーが起きる
未分類(書きかけ)
いい感じのアーキテクチャ
Firebaseを環境(Flavor)ごとにわける