【Flutter】Firebase Authenticationを使ってログイン/ユーザー登録画面を作成する(その3)

# はじめに

【Flutter】Firebase Authenticationを使ってログイン/ユーザー登録画面を作成する(その2)の続きです。
前回はただ、Firebaseプロジェクト連携をしただけですが、これからAuthenticationの実装に入ります。。
引き続きVSCodeのMac版を利用していますので、AndroidStudio利用の方は適宜読み替えて行ってみてください。

# 更新履歴
2024.1.18 初回投稿

# FirebaseAuthの実装
1. FirebaseAuthパッケージをインストールします。
    ```
    % flutter pub add firebase_auth
    ```
1. lib>main.dartを開いて、各パッケージのimportを追記します
    ```dart
    import 'package:firebase_auth/firebase_auth.dart';
    import 'package:firebase_core/firebase_core.dart';
    import 'firebase_options.dart';//←firebaseの設定を読み込みます
    ```
1. 次に「void main()」を変更します
    ```dart
    void main() {
      runApp(const LoginSample());
    }    
    ```
    ↓
    ```dart
    void main() async {//←asyncをつけ忘れしないように
      WidgetsFlutterBinding.ensureInitialized();//追加
      await Firebase.initializeApp(
        options: DefaultFirebaseOptions.currentPlatform,
      );//追加
      runApp(const LoginSample());
    }
    ```
1. 次にログイン画面用のWidgetを編集していくのですが、初学者の方向けに、riverpodを使うのではなく一旦、Statefulで実装したいと思います。
StatelessWidgetをStatefulWidgetに変更します。（VSCodeだと、「StatelessWidget」で右クリックして「Refactor...」して、「convert to StatefullWidget」が出てくるので選択すれば自動でやってくれます）
    ```dart
    class LoginPage extends StatelessWidget {
    const LoginPage({super.key});
    ```
    ↓
    ```dart
    class LoginPage extends StatefulWidget {
    const LoginPage({super.key});
    
      @override
      State<LoginPage> createState() => _LoginPageState();
    }
    
    class _LoginPageState extends State<LoginPage> {
    ```
1. state用に変数を定義します。
    ```dart
      // メッセージ表示用
      String infoText = '';
      // 入力したメールアドレス・パスワード
      String email = '';
      String password = '';
    ```
1. メールアドレスTextFieldに先ほど作成した変数に値が入るようにします。
    ```dart
    // メールアドレス入力
      TextFormField(
        decoration: const InputDecoration(labelText: 'メールアドレス'),
        onChanged: (String value) {},
      ),
    ```
    ↓
    ```dart
    // メールアドレス入力
      TextFormField(
        decoration: const InputDecoration(labelText: 'メールアドレス'),
        onChanged: (String value) {
          setState(() { //ここを追加
            email = value;//ここを追加
          });//ここを追加
        },
      ),
    ```
1. パスワード入力も同様にします。
    ```dart
    // パスワード入力
      TextFormField(
        decoration: const InputDecoration(labelText: 'パスワード'),
        obscureText: true,
        onChanged: (String value) {
          setState(() {
            password = value;
          });
        },
      ),
    ```
1. エラーなどの表示用にメッセージ表示もパスワードのTextFormFieldの下に付け加えておきます。
    ```dart
    Container(
        padding: const EdgeInsets.all(8),
        // メッセージ表示
        child: Text(infoText),
      ),
    ```
1. 最後にユーザー登録ボタンに処理を追加します。
    ```dart
    SizedBox(
        width: double.infinity,
        // ユーザー登録ボタン
        child: ElevatedButton(
          child: const Text('ユーザー登録'),
          onPressed: () {
            debugPrint('ユーザー登録');
          },
        ),
      )
    ```
    ↓
    ```dart
    SizedBox(
    width: double.infinity,
    // ユーザー登録ボタン
    child: ElevatedButton(
      child: const Text('ユーザー登録'),
      onPressed: () async {//←asyncをつけ忘れないように
      //ここから
        try {
          // メール/パスワードでユーザー登録
          final FirebaseAuth auth = FirebaseAuth.instance;
          await auth.createUserWithEmailAndPassword(
            email: email,
            password: password,
          );
          // ユーザー登録に成功した場合
         setState(() {
            infoText = "登録に成功しました！";
          });
        } catch (e) {
          // ユーザー登録に失敗した場合
          setState(() {
            infoText = "登録に失敗しました：${e.toString()}";
          });
        }
        //ここまで
      },
    ),
    ```
1. シミュレーターはこのようになっていれば成功です。
![success.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9961/5d7c8d90-6b0b-9638-94e8-cd0d197fdd0c.png)
1. Firebaseプロジェクトは以下のようになっていれば成功です。
![firebaseUserRegistration.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9961/b450d879-53f1-6a22-972a-738d68912df4.png)
# ここまでのソースコードです
```dart
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  runApp(const LoginSample());
}

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Login Sample',
      // home: const MyHomePage(title: 'Login Sample'),
      home: LoginPage(),
    );
  }
}

class LoginPage extends StatefulWidget {
  const LoginPage({super.key});

  @override
  State<LoginPage> createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  // メッセージ表示用
  String infoText = '';
  // 入力するメールアドレス・パスワード用
  String email = '';
  String password = '';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Container(
          padding: const EdgeInsets.all(24),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              // メールアドレス入力
              TextFormField(
                decoration: const InputDecoration(labelText: 'メールアドレス'),
                onChanged: (String value) {
                  setState(() {
                    email = value;
                  });
                },
              ),
              // パスワード入力
              TextFormField(
                decoration: const InputDecoration(labelText: 'パスワード'),
                obscureText: true,
                onChanged: (String value) {
                  setState(() {
                    password = value;
                  });
                },
              ),
              Container(
                padding: const EdgeInsets.all(8),
                // メッセージ表示
                child: Text(infoText),
              ),
              SizedBox(
                width: double.infinity,
                // ユーザー登録ボタン
                child: ElevatedButton(
                  child: const Text('ユーザー登録'),
                  onPressed: () async {
                    try {
                      // メール/パスワードでユーザー登録
                      final FirebaseAuth auth = FirebaseAuth.instance;
                      await auth.createUserWithEmailAndPassword(
                        email: email,
                        password: password,
                      );
                      // ユーザー登録に成功した場合
                      setState(() {
                        infoText = "登録に成功しました！";
                      });
                    } catch (e) {
                      // ユーザー登録に失敗した場合
                      setState(() {
                        infoText = "登録に失敗しました：${e.toString()}";
                      });
                    }
                  },
                ),
              )
            ],
          ),
        ),
      ),
    );
  }
}
```
次は、ログイン/ログアウト周りを実装していきたいと思います。
https://qiita.com/yoshikoba/items/5b315dea216b51375dd0

## 参考サイト
https://www.flutter-study.dev/firebase-app/authentication