1.登录分类

授权登录一键登录
一键登录在部分设备会登录不了,报白名单错误,国外的 大多数 应用使用的是授权登录,建议使用授权登录

2.申请key

在FireBase中直接创建Android 项目,会在Google Cloud 直接生成相关的key,不需要在GoogleCloud手动创建。
会生成一个Android 和 一个 Web 的配置,需要使用 Web 的 Key。

3.授权登录

class LoginActivity : BaseActivity() {    companion object {        private const val SIGN_LOGIN = 901        /**         * google自动登录,使用的是Web的key。web项目会在Android项目生成的时候自动生成         */        private const val SERVER_CLIENT_ID = "xxx"    }        private lateinit var auth: FirebaseAuth    private var mGoogleSignInClient: GoogleSignInClient? = null    private fun signInClient() {        if (mGoogleSignInClient == null) {            val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)                .requestEmail()                .requestIdToken(SERVER_CLIENT_ID)                .build();            mGoogleSignInClient = GoogleSignIn.getClient(this, gso);        }    }    private fun getGoogleIntent(): Intent {        var signInInten: Intent        if (mGoogleSignInClient == null) {            signInClient();        }        signInInten = mGoogleSignInClient!!.signInIntent;        return signInInten    }    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        ...        auth = FirebaseAuth.getInstance()        btnLoginGoogle.setOnClickListener {                signInClient()                startActivityForResult(getGoogleIntent(), SIGN_LOGIN)        }    }    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {        super.onActivityResult(requestCode, resultCode, data)        when (requestCode) {            SIGN_LOGIN -> {                val task = GoogleSignIn.getSignedInAccountFromIntent(data);                if (task == null) {                    Log.d("tag", "task:null")                }                try {                    val account = task.getResult(ApiException::class.java)                    Log.d("tag", "id:" + account.idToken)                    val firebaseCredential = GoogleAuthProvider.getCredential(account.idToken, null)                    auth.signInWithCredential(firebaseCredential)                        .addOnCompleteListener(this@LoginActivity) { task ->                            if (task.isSuccessful) {                                // Sign in success, update UI with the signed-in user's information                                Log.d("tag", "signInWithCredential:success")                                val user = auth.currentUser                                user?.getIdToken(true)                                    ?.addOnCompleteListener(OnCompleteListener<GetTokenResult?> { task ->                                        if (task.isSuccessful) {                                            val idToken: String? = task.result.token                                           // 和后台交互进行登录                                        } else {                                            // Handle error -> task.getException();                                        }                                    })                            } else {                                // If sign in fails, display a message to the user.                                Log.w("tag", "signInWithCredential:failure", task.exception)                            }                        }                } catch (e: ApiException) {                    Log.d("tag", "task:" + e.localizedMessage)                }            }        }    }}

4.一键登录

    private val REQ_ONE_TAP = 2  // Can be any integer unique to the Activity    private lateinit var oneTapClient: SignInClient    private lateinit var signInRequest: BeginSignInRequest        oneTapClient = Identity.getSignInClient(this)        signInRequest = BeginSignInRequest.builder()            .setPasswordRequestOptions(BeginSignInRequest.PasswordRequestOptions.builder().setSupported(true).build())            .setGoogleIdTokenRequestOptions(                BeginSignInRequest.GoogleIdTokenRequestOptions.builder()                    .setSupported(true)                    .setServerClientId(ServerClientId)                    .setFilterByAuthorizedAccounts(false)                    .build()            ).setAutoSelectEnabled(true).build()//https://developers.google.com/identity/one-tap/android/get-saved-credentials                oneTapClient.beginSignIn(signInRequest)                    .addOnSuccessListener(this@LoginActivity) { result ->                        try {                            startIntentSenderForResult(                                result.pendingIntent.intentSender, REQ_ONE_TAP,                                null, 0, 0, 0, null                            )                        } catch (e: IntentSender.SendIntentException) {                            Log.e("tag", "Couldn't start One Tap UI: ${e.localizedMessage}")                        }                    }                    .addOnFailureListener(this@LoginActivity) { e ->                        // No saved credentials found. Launch the One Tap sign-up flow, or                        // do nothing and continue presenting the signed-out UI.                        Log.d("tag", e.localizedMessage)                                         }

onActivityResult

REQ_ONE_TAP -> {                try {                    val credential = oneTapClient.getSignInCredentialFromIntent(data)                    val idToken = credential.googleIdToken                    val username = credential.id                    val password = credential.password                    when {                        idToken != null -> {                            // Got an ID token from Google. Use it to authenticate                            // with your backend.                            Log.d("tag", "Got ID token:" + idToken)                            val firebaseCredential = GoogleAuthProvider.getCredential(idToken, null)                            auth.signInWithCredential(firebaseCredential)                                .addOnCompleteListener(this@LoginActivity) { task ->                                    if (task.isSuccessful) {                                        // Sign in success, update UI with the signed-in user's information                                        Log.d("tag", "signInWithCredential:success")                                        val user = auth.currentUser                                        user?.getIdToken(true)                                            ?.addOnCompleteListener(OnCompleteListener<GetTokenResult?> { task ->                                                if (task.isSuccessful) {                                                    val idToken: String? = task.result.token                                                    Log.d("tag", "uid: " + user.uid)                                                    Log.d("tag", "IDToken: " + idToken)                                                } else {                                                    // Handle error -> task.getException();                                                }                                            })                                    } else {                                        // If sign in fails, display a message to the user.                                        Log.w("tag", "signInWithCredential:failure", task.exception)                                                                         }                                }                        }                        password != null -> {                            // Got a saved username and password. Use them to authenticate                            // with your backend.                            Log.d("tag", "Got password.")                        }                        else -> {                            // Shouldn't happen.                            Log.d("tag", "No ID token or password!")                        }                    }                } catch (e: ApiException) {                    // ...                }            }

5.常见错误

有可能错误是vpn的问题,检查下自己的网络

5.1 Failure16:Cannot find a matching credential.

一键登录场景下:修改了登录模式为注册登录

5.2 Failure10:Caller not whitelisted to call this API

测试账号没有加入Google Cloud

5.3 12500

检查 debug 和 release 的签名是否配置到 firebase

5.4 Firebase ID token has incorrect “aud” (audience) claim.

后台校验失败,获取到 idToken 以后还需要用 GoogleAuthProvider 的api进行二次处理

5.5 Firebase Installations Service is unavailable.

网络问题,需要在控制台才能看到错误信息,不会在登录回调里面展示。连接外网
com.google.firebase.installations.FirebaseInstallationsException: Firebase Installations Service is unavailable. Please try again later.

资料

❤️Android Google 登录接入❤️