[英]How to handle Activity.onActivityResult() with Jetpack Compose?
I am trying to implement sign-in hints in my Android app using Jetpack Compose, but this API requires an Activity
to work.我正在尝试使用 Jetpack Compose 在我的 Android 应用程序中实现登录提示,但是这个 API 需要一个
Activity
才能工作。
fun showPhoneNumberHint(activity: Activity) {
val hintRequest: HintRequest = HintRequest.Builder()
.setPhoneNumberIdentifierSupported(true)
.build()
val intent = Auth.CredentialsApi.getHintPickerIntent(apiClient, hintRequest)
val requestCode = 12345
try {
startIntentSenderForResult(activity, intent.intentSender, requestCode, null, 0, 0, 0, null)
} catch (exception: SendIntentException) {
// Error handling
}
}
So I guess that I'll have to pass the Activity object all the way down to the Composable where it's needed, which doesn't seem very clean but it should work.所以我想我必须将 Activity object 一直传递到需要它的 Composable ,这看起来不是很干净,但它应该可以工作。
But now the result of the hint will be received in the Activity's onActivityResult()
and I'm not sure what the right way is to get it back to the Composable where it's needed.但是现在提示的结果将在 Activity 的
onActivityResult()
中收到,我不确定将它返回到需要它的 Composable 的正确方法是什么。
Is there some clean/standard/alternative way to do this?有没有一些干净/标准/替代的方法来做到这一点? Preferably I'd just keep all of this logic contained inside the Composable.
最好我只是将所有这些逻辑包含在 Composable 中。
I ended up using rememberLauncherForActivityResult
in combination with the ActivityResultContracts.StartIntentSenderForResult()
contract to listen for the result.我最终将
rememberLauncherForActivityResult
与ActivityResultContracts.StartIntentSenderForResult()
合同结合使用来监听结果。 This returns a launcher
that can be used to start the intent.这将返回一个可用于启动意图的
launcher
。
Instead of Auth.CredentialsApi
, which requires the deprecated GoogleApiClient
, I'm now using the Credentials.getClient
.我现在使用的是
Credentials.getClient
而不是Auth.CredentialsApi
,它需要已弃用的GoogleApiClient
。 For this I still needed an Activity
which I got using LocalContext.current
.为此,我仍然需要使用
LocalContext.current
获得的Activity
。
val phoneNumberHintLauncher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartIntentSenderForResult()
) {
if (it.resultCode != RESULT_OK) {
return@rememberLauncherForActivityResult
}
val credential: Credential? = it.data?.getParcelableExtra(Credential.EXTRA_KEY)
val hintResult = credential?.id
if (hintResult !== null) {
phoneNumber = hintResult
}
}
val context = LocalContext.current
LaunchedEffect(Unit) {
val hintRequest: HintRequest = HintRequest.Builder()
.setPhoneNumberIdentifierSupported(true)
.build()
val phoneNumberHintIntent = Credentials.getClient(context)
.getHintPickerIntent(hintRequest)
phoneNumberHintLauncher.launch(
IntentSenderRequest.Builder(phoneNumberHintIntent)
.build()
)
}
Activity.onActivityResult()
is deprecated and you shouldn't use it even without compose. Activity.onActivityResult()
已被弃用,即使没有 compose,也不应使用它。 You should use the Activity Result APIs introduced in AndroidX Activity and Fragment.您应该使用 AndroidX Activity 和 Fragment 中介绍的 Activity Result API。
The Activity Result APIs provide a registerForActivityResult()
API for registering the result callback.活动结果 API 提供
registerForActivityResult()
API 用于注册结果回调。 registerForActivityResult()
takes an ActivityResultContract
and an ActivityResultCallback
and returns an ActivityResultLauncher
which you'll use to launch the other activity. registerForActivityResult()
接受一个ActivityResultContract
和一个ActivityResultCallback
并返回一个ActivityResultLauncher
,您将使用它来启动其他活动。
Example without compose:没有撰写的示例:
val getContent = registerForActivityResult(GetContent()) { uri: Uri? ->
// Handle the returned Uri
}
override fun onCreate(savedInstanceState: Bundle?) {
// ...
val selectButton = findViewById<Button>(R.id.select_button)
selectButton.setOnClickListener {
// Pass in the mime type you'd like to allow the user to select
// as the input
getContent.launch("image/*")
}
}
In compose use rememberLauncherForActivityResult()
instead of registerForActivityResult
:在撰写中使用
rememberLauncherForActivityResult()
而不是registerForActivityResult
:
val result = remember { mutableStateOf<Bitmap?>(null) }
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.TakePicturePreview()) {
result.value = it
}
Button(onClick = { launcher.launch() }) {
Text(text = "Take a picture")
}
result.value?.let { image ->
Image(image.asImageBitmap(), null, modifier = Modifier.fillMaxWidth())
}
The problem with the API you're trying to use is it requires the use of onActivityResult.您尝试使用的 API 的问题是它需要使用 onActivityResult。 So, you have no other option but to use it.
因此,您别无选择,只能使用它。 Try opening an issue on github requesting to update their API.
尝试在 github 上打开一个问题,请求更新他们的 API。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.