Skip to content

Instantly share code, notes, and snippets.

@wintren
Last active November 19, 2021 06:16
Show Gist options
  • Save wintren/b866232ca01cfbfb4592fe909b989efd to your computer and use it in GitHub Desktop.
Save wintren/b866232ca01cfbfb4592fe909b989efd to your computer and use it in GitHub Desktop.
Google Sign In + Firebase
package se.caspeco.mobileorder.ui.login
import android.content.Context
import android.content.Intent
import androidx.activity.result.contract.ActivityResultContract
import com.github.ajalt.timberkt.Timber
import com.google.android.gms.auth.api.signin.GoogleSignIn
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
import com.google.android.gms.auth.api.signin.GoogleSignInOptions
import com.google.android.gms.common.api.ApiException
import com.google.android.gms.tasks.Task
class GoogleSignInActivityContract : ActivityResultContract<
GoogleSignInOptions,
GoogleSignInActivityContract.Result
>() {
override fun createIntent(context: Context, input: GoogleSignInOptions?): Intent {
val client = GoogleSignIn.getClient(context, input ?: error("No GoogleSignInOptions Provided"))
return client.signInIntent
}
override fun parseResult(resultCode: Int, intent: Intent?): Result {
return handleSignInResult(GoogleSignIn.getSignedInAccountFromIntent(intent))
}
private fun handleSignInResult(completedTask: Task<GoogleSignInAccount>): Result {
return try {
Result.Success(completedTask.result)
} catch (e: Exception) {
// The ApiException status code indicates the detailed failure reason.
// Please refer to the GoogleSignInStatusCodes class reference for more information.
(e as? ApiException)?.let { Timber.w { "signInResult:failed code=" + it.statusCode } }
Result.Failure(e)
}
}
sealed class Result {
data class Success(val googleSignInAccount: GoogleSignInAccount) : Result()
data class Failure(val exception: Exception) : Result()
}
}
class LoginActivity ...
// Before onCreate
private val googleSignInRequest = registerForActivityResult(
GoogleSignInActivityContract(),
::onGoogleSignInResult
)
private val googleSignInOptions: GoogleSignInOptions
get() = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.GooglePlayServiceKey_WebClient))
.requestEmail()
.requestProfile()
.build()
private fun onGoogleSignInResult(result: GoogleSignInActivityContract.Result) = when (result) {
is GoogleAuthSuccess -> handleGoogleLogin(result.googleSignInAccount)
is GoogleAuthFailure -> Timber.e(result.exception)
}
// Trigger function
fun startGoogleSignIn() = googleSignInRequest.launch(googleSignInOptions)
private fun handleGoogleLogin(googleSignInAccount: GoogleSignInAccount) {
launchIO { // coroutine shorthand
val googleCredentials = GoogleAuthProvider.getCredential(googleSignInAccount.idToken, null)
val signInTask = FirebaseAuth.getInstance().signInWithCredential(googleCredentials)
when (signInTask.await()) {
is AuthResult -> { // <- Successfully signed in to firebase with Google Credentials
val googleName = googleSignInAccount.displayName ?: "Mr. Smith"
val googleEmail = googleSignInAccount.email ?: error("No email available")
// Handle account information ...
}
else -> {
Timber.e { "Failed" }
postEvent(LoginModels.LoginEvent.LoginFailed)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment