Google 播放计费服务超时

Google play billing service timeout

我昨天在我的应用程序中设置了 Google 播放应用程序内购买的结算,一切都按预期工作,我可以查询产品,select 他们并购买。

今天这已经改变了,它突然不起作用并返回这些错误消息:

W/BillingClient: Async task is taking too long, cancel it!
D/billingSetupError: Timeout communicating with service

返回的错误响应代码是-3。下面是我连接到服务和查询 sku 详细信息的代码(一切都在我的视图模型中,因为我使用的是完整的撰写应用程序,所以无法访问 activity 或我所在的片段)

@HiltViewModel
class StoreViewModel @Inject constructor(
private val billingClientBuilder: BillingClient.Builder
) : ViewModel(), StoreEvents, BillingClientStateListener, PurchasesUpdatedListener {

companion object {
    const val TAG = "StoreViewModel"
}

private val _state = MutableStateFlow(StoreScreenState.default)
val state: StateFlow<StoreScreenState> = _state

private val _purchaseTokens = MutableStateFlow(emptyList<String?>())
val purchaseTokens: StateFlow<List<String?>> = _purchaseTokens

private val availableSkus = listOf(
    "comic_pack",
    "elements_pack"
)

private val BACKOFF_IN_MILLIS = 500
private var backoffAttempts = 0

private var billingClient = billingClientBuilder
    .setListener(this)
    .enablePendingPurchases()
    .build()

init {

    billingClient.startConnection(this)

    viewModelScope.launch {

        state.collect {
            it.skuDetails.forEach {
                Log.d(TAG, it.toString())
            }

        }
    }
}

private suspend fun queryOneTimeProducts(): List<SkuDetails> = withContext(Dispatchers.IO) {
    if (!billingClient.isReady) {
        Log.e("TAG", "queryOneTimeProducts: BillingClient is not ready")
        return@withContext emptyList()
    }

    val availableSkus = SkuDetailsParams
        .newBuilder()
        .setSkusList(availableSkus)
        .setType(BillingClient.SkuType.INAPP)
        .build()


    return@withContext runCatching {
        val result = billingClient.querySkuDetails(availableSkus)
        result.skuDetailsList ?: emptyList()
    }.getOrNull() ?: emptyList()
}

private suspend fun handlePurchase(purchase: Purchase) {

    Log.d("purchaseComplete", purchase.toString())

    val consumeParams = ConsumeParams.newBuilder()
        .setPurchaseToken(purchase.purchaseToken)
        .build()

    withContext(Dispatchers.IO) {
        billingClient.consumePurchase(consumeParams)
    }

}

private fun updateLoading(isLoading: Boolean) {
    _state.value = state.value.copy(
        loading = isLoading
    )
}

private fun updateProducts(products: List<SkuDetails>) {
    _state.value = state.value.copy(
        skuDetails = products
    )
}

override fun StoreItemClicked(activity: Activity, name: String) {

    val selectedSku = state.value.skuDetails.find { it.title == name }

    val flowParams = selectedSku?.let {
        it
        BillingFlowParams.newBuilder()
            .setSkuDetails(it)
            .build()
    }

    flowParams?.let { billingClient.launchBillingFlow(activity, it) }
}


override fun onBillingServiceDisconnected() {
    viewModelScope.launch {
        if (backoffAttempts == 0) {
            delay(BACKOFF_IN_MILLIS.toLong())
        } else {
            delay(backoffAttempts * BACKOFF_IN_MILLIS.toLong())
        }

        if (!billingClient.isReady) {
            billingClient.startConnection(this@StoreViewModel)
            backoffAttempts++
        }
    }
}

override fun onBillingSetupFinished(billingResult: BillingResult) {
    backoffAttempts = 0

    Log.d("responsecode", billingResult.responseCode.toString())

    if (billingResult.responseCode != 0) {

        if (billingResult.responseCode == 2 || billingResult.responseCode == 3) {

            viewModelScope.launch {

                Log.d("billingSetupError", billingResult.debugMessage)

            }
        } else {
            viewModelScope.launch {

                Log.d("billingSetupError", billingResult.debugMessage)

            }
        }

    } else {

        viewModelScope.launch {

            val products = queryOneTimeProducts()

            Log.d("PRODUCTS", products.toString())

            updateProducts(products)
            updateLoading(false)
        }
    }
}

override fun onPurchasesUpdated(result: BillingResult, purchases: MutableList<Purchase>?) {
    if (result.responseCode == BillingClient.BillingResponseCode.OK && purchases != null) {
        for (purchase in purchases) {
            viewModelScope.launch {
                Log.d("purchase", purchase.toString())
                handlePurchase(purchase)
            }
        }
    } else if (result.responseCode == BillingClient.BillingResponseCode.USER_CANCELED) {

    } else {
        // Handle any other error codes.
    }
}

}

我在使用v4.1.0的时候遇到了同样的问题。 我改用了 3.0.2 版,问题消失了。 这可能是一个临时解决方案,因为不建议使用以前的版本。

也许 3.0.2 和 4.1.0 之间的版本也可以修复它。 在此处的发行说明中 https://developer.android.com/google/play/billing/release-notes 没有找到与“超时问题”相关的任何内容。