FlutterでFirebaseを使ってみる〜Google Sign In導入〜

今回はFlutterのデフォルトアプリにGoogle Sign Inを導入し、ログイン機能を実装してみたいと思います。
プロジェクトの作成は[前回](https://qiita.com/121a/items/ee488298a5b9468c3b57)までと同様です。
※今回は、Flutterプロジェクト作成時のPackage nameは**一意**になるように設定しておいてください。
<img width="1012" alt="スクリーンショット 2020-04-15 17.38.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116581/b2d0442e-06d7-19c4-68e1-4548d5bf87b8.png">

## 事前準備（共通）
Firebaseプロジェクトにて、Google Sign Inを有効化します。
Firebaseプロジェクトを開き、左ペインから**Authentication**を選択し、**ログイン方法を設定**をクリックします。

<img width="756" alt="スクリーンショット 2020-04-20 19.09.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116581/1b7e634b-ed25-da48-7e00-6edfcd19a5c8.png">

ログイン プロバイダで**Google**を選択し、**有効**にします。
※プロジェクトの公開名はそのままでも大丈夫ですが、サポートメールは必ず設定してください。

<img width="960" alt="スクリーンショット 2020-04-20 19.17.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116581/2acbfeb0-d0e1-135e-7cf1-b887da67f72c.png">


下記のように有効になっていればOKです。

<img width="1073" alt="スクリーンショット 2020-04-20 19.11.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116581/f0015f08-733c-ceb2-abe1-3820b13bf3db.png">

## 事前準備（iOS）
iOSでGoogle Sign Inを利用する場合、**OAuth client ID**をプロジェクトに設定する必要があります。
**OAuth client ID**の作成は[こちら](https://developers.google.com/identity/sign-in/ios/start-integrating)から。

まずページ中段の**Create an OAuth client ID**をクリックします。

|![create.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116581/9d4aacaa-601a-9731-11e5-0d8aae0e29ca.png)|
|:-:|

その後、[プロジェクト名] -> [iOS] -> [Bundle ID]を入力すると、
```1234567890-abcdefg.apps.googleusercontent.com```のように表示されます。
それを```com.googleusercontent.apps.1234567890-abcdefg```のように逆順に並び替え、Xcodeに貼り付けてください。

貼り付け場所は**Runner**を選択後、**Info** -> **URL Types**をクリック、表示される**URL Schemes**の部分です。

<img width="1016" alt="スクリーンショット 2020-04-20 19.21.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116581/09a5ba9c-25d4-819a-c587-d7c96ae1fbdf.png">

## pubspec.ymlの編集

事前準備が終了したところで、各ファイルの編集を行います。
**google_sign_in**と**firebase_auth**を利用して、ログイン機能を実装するので、
まずpubspec.ymlファイルに下記を追加します。

```pubspec.yml
dependencies:
  flutter:
    sdk: flutter
　// 下記の二行を追加
  google_sign_in: ^4.4.1
  firebase_auth: ^0.16.0
```

## main.dartの編集

次にmain.dartを編集します。
main.dartは殆どデフォルトのままですが、
ログイン処理を終えた後にmain画面に戻ってくるよう下記の編集を加えます。
※デフォルトのコメントは削除しています。

```main.dart
import 'package:flutter/material.dart';
// ログイン処理を行うファイル
import 'package:googlesigninsample/signin.dart';

void main() {
// runAppの対象をMyApp->Signinに変更
  runApp(SignIn());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), 
    );
  }
}
```

コメント部分以外はデフォルトのままのはず。

## signin.dartの追加
ログイン処理を行う**signin.dart**をmain.dartと同じパスに配置します。

```signin.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:googlesigninsample/main.dart';

class SignIn extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Google_Sign_In Sample',
      theme: ThemeData(
        primaryColor: Colors.red,
      ),
      home: SignInScreen(title: 'Google_Sign_In Sample'),
    );
  }
}

class SignInScreen extends StatefulWidget {
  SignInScreen({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _SignInScreenState createState() => _SignInScreenState();
}

class _SignInScreenState extends State<SignInScreen> {
  final GoogleSignIn googleSignIn = GoogleSignIn();
  final FirebaseAuth firebaseAuth = FirebaseAuth.instance;
  bool isLoggedIn = false;

  @override
  void initState() {
    super.initState();
    isSignedIn();
  }

  // 一度サインインしていれば、メイン画面を表示
  void isSignedIn() async {
    isLoggedIn = await googleSignIn.isSignedIn();
    if(isLoggedIn) {
      Navigator.push(context, MaterialPageRoute(
          builder: (context) => MyApp()
      ));
    }
  }

  Future<void> handleSignIn() async {
    //　ログイン画面の表示
    GoogleSignInAccount googleUser = await googleSignIn.signIn();
    GoogleSignInAuthentication googleAuth = await googleUser.authentication;

    //　Firebaseのユーザー認証を行う証明書を取得
    final AuthCredential credential = GoogleAuthProvider.getCredential(
        idToken: googleAuth.idToken,
        accessToken: googleAuth.accessToken
    );

    FirebaseUser firebaseUser = (await firebaseAuth.signInWithCredential(credential)).user;

    // メイン画面を表示
    if (firebaseUser != null) {
      Navigator.push(context, MaterialPageRoute(
        builder: (context) => MyApp()
      ));
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(
          widget.title,
          style: TextStyle(color: Colors.grey, fontWeight: FontWeight.bold),
        ),
        centerTitle: true,
      ),
      body: Stack(
        children: <Widget>[
          Center(
            child: FlatButton(
              onPressed: handleSignIn,
              child: Text(
                'SIGN IN WITH GOOGLE',
                style: TextStyle(fontSize: 16.0),
              ),
              color: Color(0xffdd4b39),
              highlightColor: Color(0xffff7f7f),
              splashColor: Colors.transparent,
              textColor: Colors.white,
              padding: EdgeInsets.fromLTRB(30.0, 15.0, 30.0, 15.0),
            ),
          ),
        ],
      ),
    );
  }
}
```

以上でデフォルトアプリにログイン機能が実装完了です。

いろいろコードの詳細書きたかったけど、ダメでした。。。
うーん、Firebaseの知識がまだまだ足りないなぁ。