LoginSignup
6
3

More than 3 years have passed since last update.

ActivityResultContractとViewModelを使ってFirebase Auth×Googleログインをスッキリ書く

Last updated at Posted at 2020-06-24

はじめに

AACのViewModelを用いた場合、onActivityResultが絡んだコードを書くときに辛みが発生していましたが、前回の記事を基に、Firebase AuthでのGoogleログインの処理を書いてみたら思いの外スッキリしたので記録を残しておきます。
なお、本記事ではFirebase Auth×Googleログインに関する基本的な解説はしません。

全体のソースコードはこちらです:https://github.com/masaibar/SimpleGoogleLogin

実装

詳細な差分はこちらを御覧ください。

app/build.gradle

安定版である1.1.0にはActivityResultContractが含まれていないので注意して下さい。

app/build.gradle
    implementation "androidx.activity:activity-ktx:1.2.0-alpha06"
//      implementation "androidx.fragment:fragment-ktx:1.3.0-alpha06" Fragmentの場合

MainActivity.kt

ログインに関する処理を全てViewModel側に閉じ込めることが出来るようになり、Activity側にonActivityResultを書かなくて良くなったのでボタンのリスナーを呼び出すだけになりました。

MainActivity.kt
class MainActivity : AppCompatActivity() {

    private val viewModel: MainViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        sign_in_button.setOnClickListener {
            viewModel.onClickSignIn(this)
        }
    }
}

MainViewModel.kt

onClickSignInで受け取るのはFragmentActivity型にしないとactivityResultRegistryが参照できないので気をつけましょう。

MainViewModel.kt
class MainViewModel : ViewModel() {

    private val firebaseAuth: FirebaseAuth = FirebaseAuth.getInstance()

    fun onClickSignIn(activity: FragmentActivity) {
        val googleSignInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestIdToken(activity.getString(R.string.default_web_client_id))
            .requestEmail()
            .build()
        val googleSignInClient = GoogleSignIn.getClient(
            activity,
            googleSignInOptions
        )

        activity.activityResultRegistry.register(
            "key",
            ActivityResultContracts.StartActivityForResult()
        ) { activityResult ->
            if (activityResult.data == null) {
                return@register
            }

            GoogleSignIn.getSignedInAccountFromIntent(activityResult.data)
                .addOnCompleteListener { task ->
                    if (task.isSuccessful) {
                        task.getResult(ApiException::class.java)?.let {
                            firebaseAuthWithGoogle(it)
                        }
                    }
                }
        }.launch(googleSignInClient.signInIntent)
    }

    private fun firebaseAuthWithGoogle(account: GoogleSignInAccount) {
        firebaseAuth.signInWithCredential(
            GoogleAuthProvider.getCredential(
                account.idToken,
                null
            )
        ).addOnSuccessListener {
            Log.d("Login Succeeded!!!", "${it.user?.uid}")
        }
    }
}

おわりに

ViewModel側にログインにまつわる処理を閉じ込めることが出来たおかげで、UI側をシンプルなコードに保つことが出来るようになりました。
例えばこの記事のように、MVVMとFirebase Authの実装方法は様々な議論がされてきていると思いますがActivityResultContractを利用することによって新たな可能性が生まれたと思います。

全体のソースコードはこちらです(再掲):https://github.com/masaibar/SimpleGoogleLogin

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3