Android Fragments Google Pay AutoResolveHelper.resolveTask()未调用片段中的onActivityResult

hwamh0ep  于 2023-06-23  发布在  Android
关注(0)|答案(3)|浏览(139)

我已经在应用程序中实现了Google Pay,并提出了paymentData请求,我正在使用AutoResolveHelper来显示底部表单,并通过onActivityResult获取结果。我是从Fragment而不是从Activity发出此请求的。所以我像这样传递父活动。

paymentsClient?.loadPaymentData(gpayViewModel.paymentDataRequest)?.let { task ->
            AutoResolveHelper.resolveTask(task, requireActivity(), LOAD_PAYMENT_DATA_REQUEST_CODE)
        }

问题是这个AutoResolveHelper没有在Fragment上调用onActivityResult,而是只在Activity上调用。
我读过这样的东西:
如果您从片段调用startActivityForResult(),则应调用startActivityForResult(),而不是getActivity().startActivityForResult(),因为它将导致片段onActivityResult()。
因此,它建议当AutoResolveHelper对传递的Activity调用startActivityForResult()时,将永远不会调用片段的onActivityResult。
所以现在我唯一的选择是在Activity中实现onActivityResult,并以某种方式将控制权从该Activity传递给我的子片段,但这需要一些样板代码,并且由于我的片段是可重用的,因此该解决方案并不完美。
同时,我发现这段代码以正确的方式启动了ActivityForResult,并且正确地调用了片段的onActivityResult:

val intent = Intent(activity, CardIOActivity::class.java)
        intent.putExtra(CardIOActivity.EXTRA_REQUIRE_EXPIRY, true)
        intent.putExtra(CardIOActivity.EXTRA_REQUIRE_CVV, true)
        intent.putExtra(CardIOActivity.EXTRA_REQUIRE_CARDHOLDER_NAME, true)

        startActivityForResult(intent, CARD_IO_REQUEST_CODE)

那么我可以替换这个AutoResolveHelper.resolveTask()以某种方式执行这个任务,这样就不需要onActivityResult了,或者我可以自己启动ActivityForResult?

lrpiutwd

lrpiutwd1#

截至今天,接收结果绑定到Activity。部分原因是库没有精确地使用startActivityForResult来启动这个过程;而Fragment对相同功能的支持目前是有限的。
目前基本上有两种方法可以规避这个问题(其他线程也共享了这些方法)。然而,我个人认为,在片段和活动之间混合职责并不能提供很好的代码清晰度和清晰的逻辑,所以到目前为止,我只考虑一种方法,即活动负责调用AutoResolveHelper,捕获结果并与片段共享。为了降低两者之间的耦合程度,我考虑通过合约/接口调用Activity,而不是从片段调用Activity。
一个简单的例子可能是这样的:

interface PaymentsContract {
    fun loadPaymentData(request: PaymentDataRequest, requestCode: Int)
}

让Activity实现它,并在构造时将它作为片段的引用传递,这样您的片段就可以保持可重用性,并且与Activity无关。
一旦结果准备好了,您可以选择找到有问题的片段并将onActivityResult方法传播到它,或者也可以对片段使用类似的基于合约的方法。
为了更好地理解在片段中处理这种逻辑的基本原理,并最终将反馈反馈反馈给团队,以便在未来的开发中考虑,了解更多关于具体用例的信息将是非常有用的。
希望这是有用的。
编辑:接口的另一种替代方法是使用lambda表达式来让你的片段知道在其他地方定义的可调用对象(例如:在您的活动中),并且需要在发生某些事情时调用(例如:当您的用户点击“使用Google Pay支付”按钮时)。

uklbhaso

uklbhaso2#

如果你正在使用作曲,我完善了一个很好的、干净的方法来完成这一工作,它不需要任何逻辑。所有逻辑都在视图模型和组合中处理。简而言之,Google Pay返回一个任务,可以使用ResolvableApiException而不是使用AutoResolveHelper来处理。我将在这篇文章中解释如何。
首先,您需要在Compose中定义一个启动器来启动一个活动并处理结果。我们将在后面的代码中使用这个启动器。

===YourCompose.kt===
...
    val resolvePaymentResultLauncher =
        rememberLauncherForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { result: ActivityResult ->
            when (result.resultCode) {
                RESULT_OK ->
                    result.data?.let { intent ->
                        PaymentData.getFromIntent(intent)?.let {
                            //Do whatever you want
                            viewModel.onGooglePayPaymentDialogSucceeded(it)
                        }
                    }

                RESULT_CANCELED -> {
                    // The user cancelled the payment attempt, basically the pressed X button from the native Google Pay dialog
                }
            }
        }
...//your composables

在viewModel中,您可以处理AutoResolveHandler。

===ViewModelOfYours.kt===
fun onSomethingClicked(onPendingIntentRequested: (PendingIntent) -> Unit){
        val paymentClient : PaymentsClient? = paymentViewModel.getGooglePaymentClient() //Wallet.getPaymentsClient(..) code
        val task = paymentClient?.loadPaymentData(
            PaymentDataRequest.fromJson(
                viewModelState.value.googlePayPayload ?: ""
            )
        )
        task?.addOnCompleteListener { completedTask ->
            when {
                completedTask.isSuccessful -> {
                    //No-op
                }

                completedTask.exception is ResolvableApiException -> {
                    onPendingIntentRequested((completedTask.exception as ResolvableApiException).resolution) // here we are requesting the pending intent, which will be the moment when Google Pay native dialog will be shown
                }

                else -> {
                    //TODO handle exception
                }
            }
        }
    }

最后,您需要使用组合工具中的onSomethingClicked(...)函数。触发的时刻让我们说。

====YourComposable.kt===
...
Button(onClick = { 
//remember the launcher we created? So we will launch that here, then it will trigger the activity and result will be handled where we defined `resolvePaymentResultLauncher`.
viewModelOfYours.onSomethingClicked() { pendingIntent ->
 resolvePaymentResultLauncher.launch(IntentSenderRequest.Builder(pendingIntent).build())
}
}) 
{  
//button content
}
...

我希望这有助于清理Activity中的代码,并在视图模型中处理你的逻辑。我希望我能把它分解成小的/可理解的步骤。请放心,我将感激反馈<3
归功于这里,我得到了灵感,并完善了@Odin给出的解决方案。Google pay Api in Jetpack compose - How to

unftdfkk

unftdfkk3#

这里是一个链接到工作代码。这可能不是完美的方法,但它可以完成工作。https://readyandroid.wordpress.com/onactivityresult-is-not-being-called-in-fragment/

相关问题