🐕🦺
【flutter】FirebaseOptions cannot be null when creating the default app
はじめに
flutterでアプリを作ろう!と思い、こちらの記事を参考にしていたところ、上記のエラーに遭遇しました。
エラー"FirebaseOptions cannot be null when creating the default app."の対処法をメモとして残そうと思います。
環境
macOS Monterey バージョン12.1
MacBook Pro (14インチ、2021)
$ flutter --version
Flutter 2.10.0-0.3.pre • channel dev • https://github.com/flutter/flutter.git
Framework • revision fdd0af78bb (3 days ago) • 2022-01-25 22:01:33 -0600
Engine • revision 5ac30ef0c7
Tools • Dart 2.16.0 (build 2.16.0-134.5.beta) • DevTools 2.9.2
エラー内容
flutter run で Chromeで起動したところ以下のエラーが発生。
Error: Assertion failed:
file:///Users/[ユーザー名]/development/flutter/.pub-cache/hosted/pub.dartlang.org/firebase_core_web-1.5.4/lib/src/fireb
ase_core_web.dart:273:11
options != null
"FirebaseOptions cannot be null when creating the default app."
at Object.throw_ [as throw] (http://localhost:62344/dart_sdk.js:5067:11)
at Object.assertFailed (http://localhost:62344/dart_sdk.js:4992:15)
at firebase_core_web.FirebaseCoreWeb.new.initializeApp
(http://localhost:62344/packages/firebase_core_web/firebase_core_web.dart.lib.js:252:42)
at initializeApp.next (<anonymous>)
at http://localhost:62344/dart_sdk.js:40568:33
at _RootZone.runUnary (http://localhost:62344/dart_sdk.js:40438:59)
at _FutureListener.thenAwait.handleValue (http://localhost:62344/dart_sdk.js:35360:29)
at handleValueCallback (http://localhost:62344/dart_sdk.js:35928:49)
at Function._propagateToListeners (http://localhost:62344/dart_sdk.js:35966:17)
at _Future.new.[_completeWithValue] (http://localhost:62344/dart_sdk.js:35814:23)
at async._AsyncCallbackEntry.new.callback (http://localhost:62344/dart_sdk.js:35835:35)
at Object._microtaskLoop (http://localhost:62344/dart_sdk.js:40705:13)
at _startMicrotaskLoop (http://localhost:62344/dart_sdk.js:40711:13)
at http://localhost:62344/dart_sdk.js:36188:9
エラーが出たコード(あまり関係ないので読み飛ばしてください)
main.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
Future<void> main() async {
await Firebase.initializeApp();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyAuthPage(),
);
}
}
class MyAuthPage extends StatefulWidget {
const MyAuthPage({
Key? key,
}) : super(key: key);
State<MyAuthPage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyAuthPage> {
String newUserEmail = "";
String newUserPassword = "";
String infoText = "";
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
padding: EdgeInsets.all(32),
child: Column(children: [
TextFormField(
decoration: InputDecoration(labelText: "メールアドレス"),
onChanged: (String value) {
setState(() {
newUserEmail = value;
});
},
),
const SizedBox(
height: 8,
),
TextFormField(
decoration: InputDecoration(labelText: "パスワード(6文字以上)"),
obscureText: true,
onChanged: (String value) {
setState(() {
newUserPassword = value;
});
},
),
const SizedBox(height: 8),
ElevatedButton(
onPressed: () async {
try {
final FirebaseAuth auth = FirebaseAuth.instance;
final UserCredential result =
await auth.createUserWithEmailAndPassword(
email: newUserEmail, password: newUserPassword);
final User user = result.user!;
setState(() {
infoText = "登録0K:${user.email}";
});
} catch (e) {
setState(() {
infoText = "登録NG:${e.toString()}";
});
}
},
child: Text("ユーザ登録")),
const SizedBox(
height: 8,
),
Text(infoText),
]),
)),
);
}
}
web/index.html
<!DOCTYPE html>
<html>
<head>
<base href="$FLUTTER_BASE_HREF">
<meta charset="UTF-8">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<meta name="description" content="A new Flutter project.">
<meta name="google-signin-client_id" content="619218114547-xxxx.apps.googleusercontent.com">
<!-- iOS meta tags & icons -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="signin_example">
<link rel="apple-touch-icon" href="icons/Icon-192.png">
<!-- Favicon -->
<link rel="icon" type="image/png" href="favicon.png"/>
<title>signin_example</title>
<link rel="manifest" href="manifest.json">
</head>
<body>
<script>
var serviceWorkerVersion = null;
var scriptLoaded = false;
function loadMainDartJs() {
if (scriptLoaded) {
return;
}
scriptLoaded = true;
var scriptTag = document.createElement('script');
scriptTag.src = 'main.dart.js';
scriptTag.type = 'application/javascript';
document.body.append(scriptTag);
}
if ('serviceWorker' in navigator) {
window.addEventListener('load', function () {
var serviceWorkerUrl = 'flutter_service_worker.js?v=' + serviceWorkerVersion;
navigator.serviceWorker.register(serviceWorkerUrl)
.then((reg) => {
function waitForActivation(serviceWorker) {
serviceWorker.addEventListener('statechange', () => {
if (serviceWorker.state == 'activated') {
console.log('Installed new service worker.');
loadMainDartJs();
}
});
}
if (!reg.active && (reg.installing || reg.waiting)) {
// No active web worker and we have installed or are installing
// one for the first time. Simply wait for it to activate.
waitForActivation(reg.installing || reg.waiting);
} else if (!reg.active.scriptURL.endsWith(serviceWorkerVersion)) {
// When the app updates the serviceWorkerVersion changes, so we
// need to ask the service worker to update.
console.log('New service worker available.');
reg.update();
waitForActivation(reg.installing);
} else {
// Existing service worker is still good.
console.log('Loading app from service worker.');
loadMainDartJs();
}
});
// If service worker doesn't succeed in a reasonable amount of time,
// fallback to plaint <script> tag.
setTimeout(() => {
if (!scriptLoaded) {
console.warn(
'Failed to load app from service worker. Falling back to plain <script> tag.',
);
loadMainDartJs();
}
}, 4000);
});
} else {
// Service workers not supported. Just drop the <script> tag.
loadMainDartJs();
}
</script>
<script type="module">
import { initializeApp } from "https://www.gstatic.com/firebasejs/9.6.0/firebase-app.js";
import { getAnalytics } from "https://www.gstatic.com/firebasejs/9.6.0/firebase-analytics.js";
const firebaseConfig = {
apiKey: "xxx",
authDomain: "xxx",
projectId: "xx",
storageBucket: "xxx",
messagingSenderId: "xxx",
appId: "xxx",
measurementId: "xxx"
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
const analytics = getAnalytics(app);
</script>
</body>
</html>
firebaseConfigの”xxx”の部分は自分のfirebaseのプロジェクトに示されていたものです。
つまりエラーの内容は?
エラーを読んでみると
“FirebaseOptions cannot be null when creating the default app.”
「デフォルトのアプリを作成するときにFirebaseOptionsをnullにすることはできません。」
つまり、main.dartの
await Firebase.initializeApp()
で初期化するのではなく、 以下のようにしっかり初期値を与えてあげる必要があるそうです。
await Firebase.initializeApp(options: FirebaseOptions(
apiKey: "××××",
appId: "××××",
messagingSenderId: "××××",
projectId: "××××"));
以下に解消法を示します。
対処法
以下の記事を参考にしました。
lib/config/config.dartを作成する。
lib/config/config.dart
class Configurations {
static const _apiKey = "自分のfirebaseのprojectの値";
static const _authDomain = "自分のfirebaseのprojectの値";
static const _projectId = "自分のfirebaseのprojectの値";
static const _storageBucket = "自分のfirebaseのprojectの値";
static const _messagingSenderId ="自分のfirebaseのprojectの値";
static const _appId = "自分のfirebaseのprojectの値";
String get apiKey => _apiKey;
String get authDomain => _authDomain;
String get projectId => _projectId;
String get storageBucket => _storageBucket;
String get messagingSenderId => _messagingSenderId;
String get appId => _appId;
}
セキュリティーのために.gitignoreを作成し、
lib/config
を追加する。
main.dartの Firebase.initializeApp()
の部分を以下のように修正する。
main.dart
import 'config/config.dart';
final configurations = Configurations();
Future<void> init() async {
await Firebase.initializeApp(
options: FirebaseOptions(
apiKey: configurations.apiKey,
appId: configurations.appId,
messagingSenderId: configurations.messagingSenderId,
projectId: configurations.projectId));
私はこれで動きました。
何か問題があればコメントよろしくお願いします。
Discussion
ちょうどこれで困っていました。ありがとうございます!!!!