【ログイン処理】signInWithEmailAndPasswordでFirebase Authenticationにログインする
このページでやること
このページでは、ログイン画面を作ります。
ログイン画面とは、メールアドレスとパスワードを入力して、アプリに入るための画面です。
このページでは、まだログイン処理の中身は深く説明しません。
まずは、次のような画面を作ることがゴールです。
WorkBoard
チームの会話のように、タスクを共有する
メールアドレス
パスワード
[ログイン]
新規登録はこちら
この教材では、いつも通り次の流れで進めます。
完成コードを使う
↓
一部分だけ変更する
↓
保存する・実行する
↓
画面の変化を見る
↓
次のステップへ進む
このページで出てくる単語
| 単語 | 一言説明 |
|---|---|
LoginPage | ログイン画面を作るWidget |
StatefulWidget | 画面の中で変わる値を持てるWidget |
TextEditingController | 入力欄の文字を管理する道具 |
TextField | 文字を入力するための部品 |
obscureText | パスワードを見えにくくする設定 |
FilledButton | 塗りつぶし型のボタン |
Navigator | 画面を移動するための仕組み |
setState | 画面の表示を更新する命令 |
dispose | 使い終わった道具を片付ける処理 |
Widget とは、Flutterの画面部品のことです。
npmや環境変数はこのページで必要?
このページでは、npmは使いません。
npmとは、Node.jsのパッケージを管理する道具です。
環境変数も設定しません。
環境変数とは、パソコン全体で使う設定値のことです。
このページでやることは、これだけです。
main.dartを開く
↓
LoginPageを書く
↓
保存する
↓
flutter runで確認する
Step 1:main.dartを開く
Flutterプロジェクトの中で、次のファイルを開きます。
lib/main.dart
VS Codeを使っている場合は、ターミナルで次を実行してもOKです。
code lib/main.dart
code が使えない場合は、VS Codeの左側から lib/main.dart を開いてください。
Step 2:LoginPageを追加する
AuthGate の下あたりに、次のコードを追加します。
class LoginPage extends StatefulWidget {
const LoginPage({super.key});
@override
State<LoginPage> createState() => _LoginPageState();
}
LoginPage はログイン画面です。
ここでは StatefulWidget を使います。
StatefulWidget とは、画面の中で変わる値を持てるWidgetです。
ログイン画面では、入力中のメールアドレス、パスワード、読み込み中かどうか、エラー文などが変わります。
だから StatefulWidget を使います。
Step 3:_LoginPageStateを追加する
続けて、次のコードを追加します。
class _LoginPageState extends State<LoginPage> {
final emailController = TextEditingController();
final passwordController = TextEditingController();
bool isLoading = false;
String? errorText;
@override
void dispose() {
emailController.dispose();
passwordController.dispose();
super.dispose();
}
Future<void> login() async {
setState(() {
isLoading = true;
errorText = null;
});
try {
await FirebaseAuth.instance.signInWithEmailAndPassword(
email: emailController.text.trim(),
password: passwordController.text,
);
} on FirebaseAuthException catch (e) {
setState(() {
errorText = e.message ?? 'ログインに失敗しました。';
});
} catch (_) {
setState(() {
errorText = 'ログインに失敗しました。';
});
} finally {
if (mounted) {
setState(() {
isLoading = false;
});
}
}
}
ここまでで、入力欄の準備とログイン処理の準備ができました。
emailController は、メールアドレス入力欄の文字を管理します。
passwordController は、パスワード入力欄の文字を管理します。
isLoading は、ログイン中かどうかを表します。
errorText は、ログインに失敗したときのエラー文です。
Future<void> は、時間がかかる処理を表す書き方です。
Step 4:ログイン処理を短く理解する
この部分がログイン処理です。
await FirebaseAuth.instance.signInWithEmailAndPassword(
email: emailController.text.trim(),
password: passwordController.text,
);
signInWithEmailAndPassword は、Firebase Authenticationでメールアドレスとパスワードを使ってログインする命令です。
trim() は、文字の前後にある余分な空白を消す処理です。
たとえば、メールアドレスの最後に空白が入っても、ログイン失敗しにくくなります。
入力されたメールアドレス
↓
余分な空白を消す
↓
Firebaseにログインを依頼する
Step 5:画面部分を追加する
先ほどの _LoginPageState の中に、続けて次のコードを入れます。
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColors.bg,
body: SafeArea(
child: Center(
child: SingleChildScrollView(
padding: const EdgeInsets.all(20),
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 420),
child: AppCard(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Text(
'WorkBoard',
textAlign: TextAlign.center,
style: TextStyle(
color: AppColors.lineGreen,
fontSize: 32,
fontWeight: FontWeight.w900,
),
),
const SizedBox(height: 8),
const Text(
'チームの会話のように、タスクを共有する',
textAlign: TextAlign.center,
style: TextStyle(
color: AppColors.subText,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 28),
AppTextField(
controller: emailController,
label: 'メールアドレス',
keyboardType: TextInputType.emailAddress,
),
const SizedBox(height: 12),
AppTextField(
controller: passwordController,
label: 'パスワード',
obscureText: true,
),
if (errorText != null) ...[
const SizedBox(height: 12),
ErrorBox(message: errorText!),
],
const SizedBox(height: 20),
FilledButton(
onPressed: isLoading ? null : login,
child: Text(isLoading ? 'ログイン中...' : 'ログイン'),
),
const SizedBox(height: 12),
TextButton(
onPressed: isLoading
? null
: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => const RegisterPage(),
),
);
},
child: const Text('新規登録はこちら'),
),
],
),
),
),
),
),
),
);
}
}
これでログイン画面のUIができます。
Scaffold は、Flutter画面の基本の土台です。
SafeArea は、スマホのノッチやステータスバーに画面が重ならないようにする部品です。
SingleChildScrollView は、画面が小さいときにスクロールできるようにする部品です。
ConstrainedBox は、横幅の最大サイズを決める部品です。
Step 6:画面部品の役割を見る
ログイン画面の中身は、次のように分かれています。
| 部品 | 役割 |
|---|---|
Text('WorkBoard') | アプリ名を表示する |
AppTextField | メールアドレスとパスワードを入力する |
ErrorBox | エラーがあるときだけ表示する |
FilledButton | ログインボタン |
TextButton | 新規登録画面へ移動するボタン |
全部を一気に覚えなくて大丈夫です。
まずは、画面にどの順番で並んでいるかを見るだけでOKです。
Step 7:RegisterPageがまだない場合
このコードでは、次の部分で RegisterPage を使っています。
builder: (_) => const RegisterPage(),
RegisterPage とは、新規登録画面のことです。
まだ作っていない場合、エラーになります。
その場合は、一時的に仮の RegisterPage を追加してください。
class RegisterPage extends StatelessWidget {
const RegisterPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('新規登録'),
),
body: const Center(
child: Text('新規登録画面は次のページで作ります'),
),
);
}
}
あとで本物の新規登録画面に差し替えます。
完成コードを使っている場合は、すでに RegisterPage があるので、この仮コードは不要です。
Step 8:TeamListPageがまだない場合
ログインに成功すると、AuthGate が TeamListPage に切り替えます。
まだ TeamListPage がない場合は、仮の画面を置いてください。
class TeamListPage extends StatelessWidget {
const TeamListPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('トーク'),
),
body: const Center(
child: Text('チーム一覧画面はあとで作ります'),
),
);
}
}
完成コードを使っている場合は不要です。
Step 9:保存する
main.dart を保存します。
Macの場合:
command + S
Windowsの場合:
Ctrl + S
保存しないと、変更が反映されません。
Step 10:実行する
ターミナルで実行します。
flutter run
すでに起動中の場合は、ターミナルで r を押します。
r
r はホットリロードです。
ホットリロードとは、アプリを起動したまま変更を反映する機能です。
Step 11:画面を確認する
次の画面が表示されればOKです。
WorkBoard
チームの会話のように、タスクを共有する
メールアドレス
パスワード
ログイン
新規登録はこちら
ここでは、見た目ができれば成功です。
まだユーザー登録していない場合は、ログインしてもエラーになります。
それで大丈夫です。
次のページ以降で、新規登録画面を作ります。
Step 12:一部分だけ変更してみる
試しに、サブタイトルを変更してみます。
この部分を探してください。
'チームの会話のように、タスクを共有する',
次のように変えてみます。
'チームでタスクを共有するアプリ',
保存して、ホットリロードします。
r
画面の文字が変われば成功です。
確認できたら、好きな表現に戻してOKです。
ログイン失敗を確認する
適当なメールアドレスとパスワードを入力して、ログインボタンを押してみます。
まだユーザーが登録されていなければ、エラーが表示されます。
ログインに失敗しました。
またはFirebaseからの英語メッセージが表示されることもあります。
エラーが赤い箱で表示されれば、ErrorBox が動いています。
これは成功です。
よくあるエラーと直し方
| エラー | 原因 | 直し方 |
|---|---|---|
FirebaseAuth isn't defined | importがない | firebase_auth.dart をimportする |
AppTextField isn't defined | 共通UIがない | 前ページの AppTextField を追加する |
AppCard isn't defined | 共通UIがない | 前ページの AppCard を追加する |
ErrorBox isn't defined | 共通UIがない | 前ページの ErrorBox を追加する |
RegisterPage isn't a class | 新規登録画面がまだない | 仮の RegisterPage を追加する |
setState isn't defined | StatefulWidget になっていない | State<LoginPage> の中に書く |
| 画面が変わらない | 保存していない | command + S |
| ホットリロードで直らない | 状態が残っている | R または再起動する |
FirebaseAuth isn't defined** が出たとき**
main.dart の上に、次の1行があるか確認します。
import 'package:firebase_auth/firebase_auth.dart';
なければ追加してください。
保存して、もう一度実行します。
flutter run
RegisterPage** がないと言われたとき**
新規登録画面は、まだ後のページで作ります。
今は仮の画面でOKです。
class RegisterPage extends StatelessWidget {
const RegisterPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('新規登録'),
),
body: const Center(
child: Text('新規登録画面は次のページで作ります'),
),
);
}
}
最短作業まとめ
読むのが大変な人は、ここだけ見てください。
1. lib/main.dartを開く
2. LoginPageを追加する
3. _LoginPageStateを追加する
4. 保存する
5. flutter run
6. ログイン画面が出るか確認する
実行コマンドです。
flutter run
起動中なら、
r
チェックリスト
□ LoginPageを作った
□ StatefulWidgetで作った
□ emailControllerを作った
□ passwordControllerを作った
□ login()を作った
□ AppCardを使った
□ AppTextFieldを2つ使った
□ FilledButtonを使った
□ TextButtonで新規登録画面に移動できるようにした
□ 保存した
□ flutter runでログイン画面を確認した
ミニ確認問題
Q1. LoginPageは何をする画面ですか?
回答
メールアドレスとパスワードを入力して、アプリにログインする画面です。
Q2. TextEditingControllerは何のために使いますか?
回答
入力欄に入力された文字を取得するために使います。
今回なら、メールアドレスとパスワードを取得します。
Q3. obscureText: true は何をしますか?
回答
パスワード入力欄の文字を見えにくくします。
Q4. このページでnpmや環境変数は必要ですか?
回答
必要ありません。
このページでは、main.dart にログイン画面のUIを作るだけです。
このページのまとめ
- このページでは、メールアドレスとパスワードでログインするUIを作った。
LoginPageはログイン画面。- 入力欄の文字は
TextEditingControllerで管理する。 - パスワード入力欄には
obscureText: trueを使う。 - ログインボタンには
FilledButtonを使う。 - 新規登録画面へは
Navigatorで移動する。 - エラーがあるときは
ErrorBoxで表示する。 - このページではnpmや環境変数は不要。
- まずは保存して、画面の変化を見ることが大切。
次のページでやること
次のページでは、ログインボタンを押したときの処理をもう少し詳しく見ます。
signInWithEmailAndPassword を使って、Firebase Authenticationにログインする流れを理解します。
