Open23

Flutter初期設定・トラブルシュート集

ピン留めされたアイテム
wakewake

1. インストールコピペ用

ほぼ必須パッケージインストール

flutter pub add go_router flutter_hooks hooks_riverpod flutter_keyboard_visibility recase dev:flutter_launcher_icons dev:flutter_native_splash

自分用ユーティリティパッケージ込みver

flutter pub add go_router flutter_hooks hooks_riverpod flutter_keyboard_visibility recase flutter_utilities_drdng dev:flutter_launcher_icons dev:flutter_native_splash

2. 多言語対応

下へ

3. flavorize

https://zenn.dev/wake/articles/flutter-flavorizr

4. フォルダ構成

dirs=("enums" "pages/home" "pages/not_found" "providers" "models")
for dir in "${dirs[@]}"; do mkdir -p "lib/$dir"; done

launch.json

mkdir .vscode && echo '{"version": "0.2.0","configurations": [{"name": "Flutter","request": "launch","type": "dart","program": "lib/main.dart"},]}' > .vscode/launch.json

必ずやる設定

モデル系

freezed

flutter pub add freezed_annotation dev:build_runner dev:freezed

formJson/toJsonも生成する場合

flutter pub add freezed_annotation dev:build_runner dev:freezed json_annotation dev:json_serializable

Isar

flutter pub add path_provider isar isar_flutter_libs dev:isar_generator dev:build_runner

Firebase

Firebase最低限インストール(analytics, crashlytics, performance)

flutter pub add firebase_core firebase_analytics firebase_crashlytics firebase_performance

Auth (+UI)

flutter pub add firebase_auth firebase_ui_auth firebase_ui_localizations

https://zenn.dev/wake/articles/flutter-firebase-auth-and-firebase-ui-auth

Firestore (+ODM)

flutter pub add cloud_firestore cloud_firestore_odm json_annotation dev:build_runner dev:cloud_firestore_odm_generator dev:json_serializable

firestoreはビルドに5分とかかかるので短縮するためにios/Podfileに以下を追加する
10.22.0の部分はfirebase_corefirebase_sdk_version.rbで指定されたバージョンに直す

target 'Runner' do
  use_frameworks!
  use_modular_headers!

+  pod 'FirebaseFirestore',
+    :git => 'https://github.com/invertase/firestore-ios-sdk-frameworks.git',
+    :tag => '10.22.0'

  flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
  target 'RunnerTests' do
    inherit! :search_paths
  end
end
Hidden comment
wakewake

多言語対応は最初からする

https://pub.dev/packages/easy_localization

flutter pub add easy_localization easy_localization_loader

easy_localization_loader は言語ファイルをjsonで定義する場合は不要です。(私はjsonよりyamlが好きなので)

info.plist

	<key>CFBundleLocalizations</key>
	<array>
		<string>en</string>
		<string>ja</string>
	</array>

言語ファイルを設置 (json定義ならyaml→jsonにして)

mkdir -p assets/l10n
touch assets/l10n/en-US.yaml assets/l10n/ja-JP.yaml

言語ファイルの例はこちら

pubspec.yamlを更新

flutter:
  assets:
+    - assets/l10n/

main.dart

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await EasyLocalization.ensureInitialized();

  runApp(EasyLocalization(
    path: 'assets/l10n',
    assetLoader: const YamlAssetLoader(), // json定義なら不要
    supportedLocales: const [Locale('ja', 'JP'), Locale('en', 'US')],
    fallbackLocale: const Locale('en', 'US'),
    child: const ProviderScope(child: MyApp()),
  ));
}

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      localizationsDelegates: context.localizationDelegates,
      supportedLocales: context.supportedLocales,
      locale: context.locale,
      home: MyHomePage()
    );
  }
}
old
Hidden comment
Hidden comment
wakewake

FirestoreODMを使ってハマった(v1.0.0-dev.58)

XXXCollectionReferenceが生成されない

pubspec.yamlに以下を追加

dependencies:
  xxxx: xxx
dev_dependencies:
  xxxx: xxx
#↓追加
dependency_overrides:
  graphs: 2.2.0
  build_runner: 2.4.3

https://github.com/firebase/flutterfire/issues/10956


Undefined name '_$XXXFieldMap'.

以下の内容でbuild.yamlを作成

targets:
  $default:
    builders:
      cloud_firestore_odm_generator:
        enabled: true
        generate_for:
          include:
            - lib/*
            - lib/**
      json_serializable:
        enabled: true
        generate_for:
          include:
            - lib/*
            - lib/**
        options:
          create_field_map: true
      source_gen|combining_builder:
        options:
          ignore_for_file:
            - "type=lint"

https://github.com/firebase/flutterfire/issues/10844

documentの更新が追いついてない様子

wakewake

firebase function の github actions deploy
https://github.com/w9jds/firebase-action
オプションのロールもフルに付与したほうが、後で作り直すことにならないので楽

If updating Firestore Rules, include the Firebase Rules Admin role.
If updating Firestore Indexes, include the Cloud Datastore Index Admin role.
If deplying Hosting files, include the Firebase Hosting Admin role.

の3つはなかったので「Firebase 管理者」で代用した


さらに追加で「Artifact Registry 管理者」ロールを追加しないと下のようなwarningが発生し、少額の課金が発生するっぽい

functions: Unhandled error cleaning up build images. This could result in a small monthly bill if not corrected. You can attempt to delete these images by redeploying or you can delete them manually at https://console.cloud.google.com/artifacts/docker/do-it--dev/us-central1/gcf-artifacts
wakewake

暗号化の輸出コンプライアンスを設定する
info.plistに追加

<key>ITSAppUsesNonExemptEncryption</key>
<false/>
wakewake

FCMのペイロード(androidは未検証)

  • 音を鳴らす
  • onBackgroundMessage()を発火させる
{
	topic: "topic",
	notification: {
		title: "title",
		body: "body",
	},
	android: {
		notification: {
			sound: "default",
			defaultSound: true,
		}
	},
	apns: {
		payload: {
			aps: {
				sound: "default", // sound
				contentAvailable: true, // onBackgroundMessage()を発火させるために必要
			}
		}
	}
}
wakewake

Firebase CrashlyticsのdSYM自動アップロード

公式ではこう説明があり、flavorを利用しているため手動で設定する必要があるが、公式の説明にあるスクリプトはflavorに対応していなく、調べる必要があった。

結論

open ios/Runner.xcworkspace

して、サイドメニュー「Runner」 > TARGETS「Runner」 > Build Phasesで
「+」を押して「New Run Script Phase」を選ぶ。名前は

[firebase_crashlytics] Crashlytics Upload Symbols

とかで下記スクリプト追加

${PODS_ROOT}/FirebaseCrashlytics/run

Input Filesに

$(SRCROOT)/$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)

を追加

https://github.com/firebase/flutterfire/issues/10507#issuecomment-1558062764

wakewake

flutter_web_pluginsはwebビルド以外ではコンパイルエラーになる?

WebとmacOSを同じFlutterコードで実装していた際、macOSのビルド時に

../../../fvm/versions/stable/packages/flutter_web_plugins/lib/src/navigation/url_strategy.dart:55:16: Error: 'PlatformLocation' isn't a type.
  final ui_web.PlatformLocation _platformLocation;
               ^^^^^^^^^^^^^^^^
Unhandled exception:
FileSystemException(uri=org-dartlang-untranslatable-uri:dart%3Aui_web; message=StandardFileSystem only supports file:* and data:* URIs)
#0      StandardFileSystem.entityForUri (package:front_end/src/api_prototype/standard_file_system.dart:34)
#1      asFileUri (package:vm/kernel_front_end.dart:748)
#2      writeDepfile (package:vm/kernel_front_end.dart:886)
<asynchronous suspension>
#3      FrontendCompiler.compile (package:frontend_server/frontend_server.dart:673)
<asynchronous suspension>
#4      starter (package:frontend_server/starter.dart:101)
<asynchronous suspension>
#5      main (file:///Volumes/Work/s/w/ir/x/w/sdk/pkg/frontend_server/bin/frontend_server_starter.dart:13)
frontend_server_starter.dart:13
<asynchronous suspension>

Target kernel_snapshot failed: Exception

Command PhaseScriptExecution failed with a nonzero exit code
** BUILD FAILED **

Error: Build process failed

といったエラーに出会った。
どうもmain関数内webビルド用に記述していたsetUrlStrategy(PathUrlStrategy());がいけないらしい。
その行とimport行をコメントアウトすればエラーが消えた。

解決

main_web.dart

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

import 'main.dart' as app;

void main() {
  debugPrint('main_web.dart');
  setUrlStrategy(PathUrlStrategy());
  app.main();
}

というファイルを用意し

flutter run -d chrome -t lib/main_web.dart

というコマンドで実行して回避した

Hidden comment
wakewake

TextFieldを右寄せすると末尾の空白が表示されない

のでこうする

return Align(
  alignment: Alignment.centerRight,
  child: IntrinsicWidth(
    child: TextFormField(
      readOnly: !isEditing.value,
      focusNode: focus,
      controller: ctrl,
      decoration: const InputDecoration(
        border: InputBorder.none,
      ),
      onTap: () => isEditing.value = true,
      onTapOutside: (_) {
        isEditing.value = false;
        onSaved(ctrl.text);
      },
      onFieldSubmitted: onSaved,
    ),
  ),
);