如何使用 Jetpack Compose 处理 Activity.onActivityResult()?

How to handle Activity.onActivityResult() with Jetpack Compose?

我正在尝试使用 Jetpack Compose 在我的 Android 应用程序中实现 sign-in hints,但是这个 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
    }
}

所以我想我必须将 Activity 对象一直传递到需要它的可组合项,这看起来不是很干净,但它应该可以工作。

但现在提示的结果将在 Activity 的 onActivityResult() 中收到,我不确定将其返回到需要它的可组合项的正确方法是什么.

有什么 clean/standard/alternative 方法可以做到这一点吗?我最好将所有这些逻辑都包含在可组合项中。

Activity.onActivityResult() 已弃用,即使没有撰写也不应该使用它。您应该使用 AndroidX Activity 和 Fragment.Activity 中引入的 Activity 结果 APIs。

Activity 结果 API 提供 registerForActivityResult() API 用于注册结果回调。 registerForActivityResult() 需要一个 ActivityResultContract 和一个 ActivityResultCallback 和 returns 一个 ActivityResultLauncher,您将使用它们来启动另一个 activity.

没有撰写的例子:

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/*")
    }
}

在撰写中使用 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())
}

您尝试使用的 API 的问题是它需要使用 onActivityResult。所以,你别无选择,只能使用它。尝试在 github 上打开一个问题,请求更新他们的 API.

我最终使用 rememberLauncherForActivityResult 结合 ActivityResultContracts.StartIntentSenderForResult() 合约来监听结果。这个returns一个可以用来启动intent的launcher

而不是 Auth.CredentialsApi,它需要已弃用的 GoogleApiClient,我现在使用的是 Credentials.getClient。为此,我仍然需要一个 Activity,我使用 LocalContext.current.

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()
    )
}