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
相关产品推荐
相关产品推荐

