日々ろぐ

人に優しく٩( 'ω' )و

FlutterでFirebaseAuthentication使ってTwitterログインしてみる

タイトルの通り。

10月からFlutter触ろうと思ってたので、試しにログイン処理など作ってみました。
ネットを徘徊してると、ログインだけで完結してるものや、Googleログインの情報はよく見かけたんですが、何故かTwitterログインの情報が少なかったので、Twitterログインで試しています。

あと、ログインの状態管理に ChangeNotifierProvider を利用しました。
Flutterでは状態管理の方法が色々あるようです。
アプリの規模やユースケースによって方法を考えればいいのかなと思いますが、そこまで正直わかってない。。。
まずは第一歩というところで、公式ドキュメントのやり方を参考にこの方法でやってみました。

flutter.dev

ちょいちょい耳にはさむBLoCは、イメージは分かるんですけどお作法とかまだよく分かってません。

Flutter is ?

AndroidiOSのアプリをDartで書けるUIツール。
各パーツや画面をWidgetとして定義して、それを組み合わせてUIを作っていくというのはコンポーネント指向に近いのかなと思うなどしています。
Widget単位で再構築するので処理速度も速いとかなんとか。
ただ、状態の持たせ方によっては不要なビルドが走りまくってパフォーマンスがガタ落ちするとも聞いたので、設計は大事。

flutter.dev

あと、ホットリロードがいい感じです。

Flutterの環境構築

公式ドキュメントの手順通りに構築を進めていって、特に躓くところはなかったです。
SDK落としてきてPATH通して flutter doctor で診察して、足りないものを追加するという流れを繰り返します。

コードなど

ログイン処理と、状態管理の確認をしたかったので
・ログイン画面
・ログイン状態によりメッセージが変化する画面
の2画面の構成です。

github.com

パッケージのバージョンによってちょちょいエラーが出てたので、それは後述します。

Firebase

Firebase の公式ドキュメント通りに進めます。

firebase.google.com

Firebase Authentication を利用するので、これ用のプロジェクトを新たに追加してTwitter認証を有効にしておきます。
プロジェクトにアプリを追加するんですが、今回は AndroidApp で試しました。
google-services.json をダウンロードしてプロジェクトに追加してな」と言われるので、その通りに。

Twitter

Twitter の Developer アカウントを登録して、App を追加しておきます。
Callback URL を設定する際に、Firebase Authentication で発行されるURLだけ設定するとエラーになることがあります。
ここらへんのstackoverflowなどを参考に、「twittersdk://」も追加しました。

stackoverflow.com

Android限定ですかね?

パッケージ周り

Firebase のパッケージのバージョンで、google-services プラグインのバージョンとの互換性なのか分からないですが、一部うまくいかないケースがありました。
色々とバージョンを変えて試してみて、一応この形で落ち着いています。

android/app/build.gradle

buildscript {
    (省略)
    dependencies {
        classpath 'com.android.tools.build:gradle:3.2.1'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        // Add
        classpath 'com.google.gms:google-services:4.2.0'
    }
    ...
}

pubspec.yaml

environment:
  sdk: ">=2.1.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter
  provider: ^3.0.0
  firebase_core: ^0.4.0  # add dependency for Firebase Core
  firebase_auth: ^0.14.0+5
  flutter_twitter_login: ^1.1.0

あと、Androidエミュレータによっては以下の設定も必要になるようです。

android/gradle.properties

android.useAndroidX=true
android.enableJetifier=true

ここら辺は触っていって知見を貯めていくしかないかなぁ。。

状態管理について

ChangeNotifier を継承した AuthModel にログイン情報を持たせてます。
ログイン・ログアウトのタイミングで AuthModelisLogindisplayName を変更して、 notifyListeners() によって状態の変化を通知する流れにしてます。
(( displayName をセットするタイミングで notifyListeners() を呼ぶ必要はなかったかな..))

今回は、最上位のWidget(MyApp)にproviderとして AuthModel を指定しているので、それにぶら下がっている LoginPageNextPageAuthModel の状態を取得できるような形です。

LoginPage クラスでは、ログイン・ログアウトの処理を実施したタイミングで AuthModel にログイン状態をセットしています。

login_page.dart

  void _twitterLogin() async {

    ...
     省略(ログイン処理を実施)
    ...

    // ログイン状態の更新
    if (_twitterLoginStatus == TwitterLoginStatus.loggedIn && _currentUser != null) {
      _authModel.setLoginState(true);
      _authModel.setDisplayName(_currentUser.displayName);
    }
  }

NextPage クラスでは、 AuthModel から状態を取得するのに以下のような形でプロバイダから値を取得してます。
これによって、ログイン状態が変化するごとにWidgetがビルドしなおされ、表示されるログイン情報を更新していきます。

next_page.dart

class NextPage extends StatelessWidget {
  AuthModel _authModel;

  @override
  Widget build(BuildContext context) {
    _authModel = Provider.of<AuthModel>(context);

    ...
    以下略
    ...
  }

  void setDisplayMessage(){
    if(_authModel.isLogin) {
      _loginStateMessage = "Hi, " + _authModel.displayName;
    }
  }
}

雑感

割と簡単に書けるなーと思う反面、Dartを知らなすぎるので良い書き方がまだ分かってないので、そこら辺を知っていくともっと楽しくなるんだろうなと思ってます。
Flutterに関しても、コードの構成とかディレクトリ構成とか、気持ちのいい実装の形ってあると思うので、そういうのは色んなプロジェクト見ながら考えていこうかなと。

あとはIonic触った時も思ったんですけど、やっぱライブラリやパッケージのバージョンと、エミュレータに対してはもっと気を配らないといけないなと思いました。

とりあえず今日はここまで。