如何在Jetpack Compose中适配旧版华为应用内购SDK?
解决Jetpack Compose集成华为旧版应用内购SDK的Activity结果处理问题
针对你遇到的华为旧版IAP SDK无法适配Compose rememberLauncherForActivityResult的问题,这里提供几种无需反射的可行方案:
方案1:宿主Activity代理 + 数据流传递结果
利用单Activity架构的特性,在宿主Activity中保留传统的onActivityResult逻辑,通过数据流将结果同步到Composable组件,完全不依赖SDK内部实现:
- 在宿主Activity中定义共享数据流,用于转发内购结果:
class MainActivity : ComponentActivity() { val iapResultFlow = MutableSharedFlow<ActivityResult>(extraBufferCapacity = 1) override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) // 用你实际的内购请求码替换1001 if (requestCode == 1001) { iapResultFlow.tryEmit(ActivityResult(resultCode, data)) } } }
- 在Composable中收集数据流并处理结果:
@Composable fun IapPurchaseButton() { val mainActivity = LocalContext.current as MainActivity val lifecycleOwner = LocalLifecycleOwner.current // 收集内购结果 LaunchedEffect(lifecycleOwner) { mainActivity.iapResultFlow.collect { result -> when (result.resultCode) { Activity.RESULT_OK -> { // 处理内购成功逻辑 } else -> { // 处理失败/取消逻辑 } } } } Button(onClick = { // 传入Status实例和宿主Activity发起内购 yourIapStatusInstance.startResolutionForResult(mainActivity, 1001) }) { Text("发起内购") } }
方案2:自定义ActivityResultContract适配Status
通过自定义ActivityResultContract,直接封装Status.startResolutionForResult的调用逻辑,让它适配Compose的rememberLauncherForActivityResultAPI:
- 实现自定义Contract:
class IapStatusContract : ActivityResultContract<Status, ActivityResult>() { override fun createIntent(context: Context, input: Status): Intent = Intent() override fun parseResult(resultCode: Int, intent: Intent?): ActivityResult = ActivityResult(resultCode, intent) override fun launch( registry: ActivityResultRegistry, requestCode: Int, input: Status, options: ActivityOptionsCompat? ) { val callback = registry.register(requestCode, this) { result -> callback.onActivityResult(result) } // 获取当前Activity实例并调用SDK方法 val activity = (registry as ComponentActivity).activity input.startResolutionForResult(activity, requestCode) } }
- 在Composable中使用该Contract:
@Composable fun IapPurchaseButton() { val iapLauncher = rememberLauncherForActivityResult(IapStatusContract()) { result -> // 直接处理内购结果 if (result.resultCode == Activity.RESULT_OK) { // 成功逻辑 } } Button(onClick = { // 传入Status实例发起内购 iapLauncher.launch(yourIapStatusInstance) }) { Text("发起内购") } }
方案3:直接使用ActivityResultRegistry注册回调
在Composable中通过LocalActivityResultRegistryOwner获取注册表,手动注册结果回调,无需修改宿主Activity:
@Composable fun IapPurchaseButton() { val registryOwner = LocalActivityResultRegistryOwner.current val context = LocalContext.current val requestCode = remember { 1001 } val yourIapStatusInstance = remember { /* 获取你的Status实例 */ } // 定义结果回调 val resultCallback = remember { ActivityResultCallback<ActivityResult> { result -> // 处理内购结果 } } // 注册回调并在组件销毁时注销 DisposableEffect(registryOwner, requestCode) { val registration = registryOwner.activityResultRegistry.register( "iap_purchase_key", requestCode, ActivityResultContracts.StartActivityForResult(), resultCallback ) onDispose { registration.unregister() } } Button(onClick = { yourIapStatusInstance.startResolutionForResult(context as ComponentActivity, requestCode) }) { Text("发起内购") } }
方案对比
- 方案1:实现最简单,兼容性强,适合快速迁移场景,但需要宿主Activity配合添加数据流逻辑。
- 方案2:最贴合Compose的ActivityResult设计理念,封装性好,后续维护更方便,但需要理解Contract的实现细节。
- 方案3:无需修改宿主Activity,完全在Composable中处理,但需要手动管理回调的注册与注销,需注意生命周期问题。
内容的提问来源于stack exchange,提问作者rolandl
相关产品推荐
相关产品推荐

