kotlin - 如何将 registerForActivityResult 与 StartIntentSenderForResult 合同一起使用?
问题描述
我正在编写一个 Kotlin 应用程序并使用 Firebase 进行身份验证。正如onActivityResult
现在已经过时的那样,我正在尝试将我的应用程序迁移到使用registerForActivityResult
. 我有一个指向 Google 帐户功能的链接,它以 Google 登录流程开始,如此处所示。我的代码:
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
在片段中调用where onCreateView
,showLinkWithGoogle
当用户点击屏幕上的按钮时调用。这完美地工作。我使用 查找了一个示例,我找到的最好的示例在此页面registerForActivityResult
的底部。我添加了这段代码:
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())
非常感谢!
解决方案
对于这个用例,您不需要一个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()
}
}
}
}
}
为了让我的生活更轻松,我创建了一个扩展函数,它检查登录是否成功,然后执行一段代码(在这种情况下,获取帐户),同时缓存任何异常。此外,在您的块内,您可以访问 ActivityResult 的实例this
:
inline fun ActivityResult.checkResultAndExecute(block: ActivityResult.() -> Unit) =
if (resultCode == Activity.RESULT_OK) runCatching(block)
else Result.failure(Exception("Something went wrong"))
推荐阅读
- c - 将 mkmf 与 Ruby ext 一起使用 使用 -L 和 -I 和 -l 链接静态库
- javascript - 如何阻止在子元素上触发事件而不是添加指针事件?
- javascript - 如何在不使用 Tampermonkey 扩展的情况下加载 JS
- python - 如何多次拆分输入文本
- java - 如何将底页窥视高度设置为视图下方?
- python - 如何在循环中使用变量来创建特定的变量名
- angular - 错误:使用 ng serve --aot 时找不到模块
- react-native - 如何在 react native expo 项目中制作 iOS 和 android 文件夹
- xslt - 使用 XSLT 获取字符串中的文本
- pandas - Pandas - 按组/子组执行滚动平均