问题描述
我正在编写 Kotlin 应用并使用 Firebase 进行身份验证。
由于 onActivityResult
现在已弃用,我正在尝试迁移我的应用以使用 registerForActivityResult
。我有一个指向 Google 帐户功能的链接,该链接从 Google 登录流程开始,如图 here 所示。我的代码:
private fun initGoogleSignInClient() =
activity?.let {
// Configure Google Sign In
val gso =
GoogleSignInoptions.Builder(GoogleSignInoptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.default_web_client_id))
.requestemail()
.build()
// Build a GoogleSignInClient with the options specified by gso.
viewmodel.googleSignInClient = GoogleSignIn.getClient(it,gso)
}
private fun showLinkWithGoogle() =
startActivityForResult(viewmodel.googleSignInClient.signInIntent,RC_LINK_GOOGLE)
其中 initGoogleSignInClient
在片段的 onCreateView
中被调用,而 showLinkWithGoogle
在用户点击屏幕上的按钮时被调用。这完美地工作。
我查找了一个使用 registerForActivityResult
的示例,我找到的最好的示例位于 this 页面的底部。我添加了这个代码:
private val linkWithGoogle =
registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) {
viewmodel.handleGoogleResult(it.data)
}
private fun showLinkWithGoogle() =
linkWithGoogle.launch(IntentSenderRequest.Builder(viewmodel.googleSignInClient.signInIntent))
但意识到 IntentSenderRequest.Builder
需要 IntentSender
而不是 Intent
。我还没有找到任何关于如何从 IntentSender
构建 Intent
的示例,也没有找到从我的 GoogleSignInClient
中获取 registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult())
的方法。
谁能提供一个使用 char.IsDigit
的完整示例?
非常感谢!
解决方法
对于此用例,您不需要 ActivityResultContracts
类型的 StartIntentSenderForResult
,而是 StartActivityForResult
类型之一。这是一个示例(因为您没有提供完整的实现):
片段
private val googleRegisterResult =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
result.checkResultAndExecute {
val task = GoogleSignIn.getSignedInAccountFromIntent(data)
val account = task.getResult(ApiException::class.java)
loginViewModel.onEvent(LoginRegistrationEvent.SignInWithGoogle(account))
}.onFailure { e -> toast("Error: ${e.message}") }
}
override fun onViewCreated(view: View,savedInstanceState: Bundle?) {
super.onViewCreated(view,savedInstanceState)
myGoogleSignInButton.setOnClickListener {
googleRegisterResult.launch(viewModel.googleSignInClient.signInIntent)
}
}
然后,在您的视图模型中,您可以像往常一样处理登录,唯一的区别是,您不再需要 RC_SIGN_IN
视图模型示例
class YourViewModel : ViewModel() {
fun onEvent(event: LoginRegistrationEvent) {
when(event) {
is LoginRegistrationEvent.SignInWithGoogle -> {
viewModelScope.launch {
val credential = GoogleAuthProvider.getCredential(event.account.idToken)
Firebase.auth.signInWithCredential(credential).await()
}
}
}
}
}
为了让我的生活更轻松,我创建了一个扩展函数,用于检查登录是否成功,然后执行代码块(在本例中为获取帐户),同时缓存任何异常。此外,在您的代码块中,您可以通过 this
:
inline fun ActivityResult.checkResultAndExecute(block: ActivityResult.() -> Unit) =
if (resultCode == Activity.RESULT_OK) runCatching(block)
else Result.failure(Exception("Something went wrong"))