You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetpack Compose集成Google Wallet:onActivityResult结果传递至Compose页面问题

解决Jetpack Compose中Google Wallet推送令牌化结果传递问题

由于Google Wallet的pushTokenize API仍依赖已废弃的onActivityResult机制,要将令牌化结果传递到Compose页面,可通过ViewModel + 数据流的方式实现,具体步骤如下:

1. 创建共享ViewModel管理结果状态

定义ViewModel,用MutableStateFlow承载令牌化的结果状态,让Compose页面能主动监听状态变化:

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch

class WalletTokenizeViewModel : ViewModel() {
    private val _tokenizeResult = MutableStateFlow<TokenizeResult?>(null)
    val tokenizeResult: StateFlow<TokenizeResult?> = _tokenizeResult

    // 发送令牌化结果到数据流
    fun sendTokenizeResult(result: TokenizeResult) {
        viewModelScope.launch {
            _tokenizeResult.emit(result)
        }
    }

    // 重置结果状态,避免重复处理历史结果
    fun resetResult() {
        viewModelScope.launch {
            _tokenizeResult.emit(null)
        }
    }

    // 密封类定义结果类型,区分成功/失败场景
    sealed class TokenizeResult {
        data class Success(val tokenId: String) : TokenizeResult()
        object Failure : TokenizeResult()
    }
}

2. 在宿主Activity中接收结果并传递到ViewModel

在承载Compose的Activity中实现onActivityResult,将原生结果转换为ViewModel定义的状态并发送:

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.lifecycle.ViewModelProvider

class MainActivity : ComponentActivity() {
    private lateinit var viewModel: WalletTokenizeViewModel
    private val REQUEST_CODE_PUSH_TOKENIZE = 1001

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        viewModel = ViewModelProvider(this)[WalletTokenizeViewModel::class.java]

        setContent {
            // 传入ViewModel到你的Compose页面
            WalletApp(viewModel = viewModel)
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == REQUEST_CODE_PUSH_TOKENIZE) {
            val result = when (resultCode) {
                Activity.RESULT_OK -> {
                    val tokenId = data?.getStringExtra(TapAndPay.EXTRA_ISSUER_TOKEN_ID) ?: ""
                    WalletTokenizeViewModel.TokenizeResult.Success(tokenId)
                }
                Activity.RESULT_CANCELED -> {
                    WalletTokenizeViewModel.TokenizeResult.Failure
                }
                else -> null
            }
            result?.let { viewModel.sendTokenizeResult(it) }
        }
    }
}

3. 在Compose页面中监听结果并处理逻辑

在Compose页面里,收集ViewModel的数据流,根据结果更新UI或执行后续业务逻辑:

import androidx.compose.foundation.layout.Column
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.platform.LocalContext
import androidx.lifecycle.viewmodel.compose.viewModel
import com.google.android.gms.tapandpay.TapAndPayClient
import com.google.android.gms.tapandpay.PushTokenizeRequest

@Composable
fun WalletApp(viewModel: WalletTokenizeViewModel = viewModel()) {
    val tokenizeResult by viewModel.tokenizeResult.collectAsState()
    val context = LocalContext.current
    val tapAndPayClient = TapAndPayClient.getClient(context)

    Column {
        Button(onClick = {
            // 构建推送令牌化请求(对应你原有的Java代码转Kotlin)
            val pushTokenizeRequest = PushTokenizeRequest.Builder()
                .setOpaquePaymentCard(opc)
                .setNetwork(cardNetwork)
                .setTokenServiceProvider(tokenProvider)
                .setDisplayName("My Card")
                .setLastDigits("1234")
                .setUserAddress(userAddress)
                .build()

            // 调用pushTokenize,传入当前Activity实例
            tapAndPayClient.pushTokenize(
                context as Activity,
                pushTokenizeRequest,
                REQUEST_CODE_PUSH_TOKENIZE
            )
            // 重置结果状态,避免触发历史结果的处理逻辑
            viewModel.resetResult()
        }) {
            Text("添加至Google Wallet")
        }

        // 监听结果变化,执行对应逻辑
        LaunchedEffect(tokenizeResult) {
            tokenizeResult?.let { result ->
                when (result) {
                    is WalletTokenizeViewModel.TokenizeResult.Success -> {
                        // 处理成功逻辑,比如展示令牌ID、更新本地数据
                        println("令牌化成功,Token ID: ${result.tokenId}")
                    }
                    WalletTokenizeViewModel.TokenizeResult.Failure -> {
                        // 处理失败逻辑,比如弹出错误提示、引导用户重试
                        println("令牌化失败,请重试")
                    }
                }
            }
        }
    }
}

补充提示

  • 确保通过LocalContext.current as Activity能正确获取到宿主Activity实例
  • 每次触发令牌化前调用resetResult(),防止重复处理之前的结果
  • 可根据业务需求扩展TokenizeResult密封类,比如添加错误码、错误信息字段

内容的提问来源于stack exchange,提问作者Sam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 14:36:52