apologies if this is trivial - I am new to Kotlin and coroutines (read Elizarov etc.)
I have an Activity that, in its onCreate(), needs to get a price from the Play Store. I wrote this:
...
lifecycleScope.launch {
val pd = StoreHelper.getProductDetails(pp!!)
val price = pd?.oneTimePurchaseOfferDetails?.formattedPrice
if (price != null) {
buyNowBtn.text = getString(R.string.buy_price, price)
} else {
buyNowBtn.text = getString(R.string.buy_no_price)
}
}
...
Then, the helper's getProductDetails() I copy-pasted from the docs (notice suspend):
suspend fun getProductDetails(PitchProductId: Long) : ProductDetails? {
var pd: ProductDetails? = null
val queryProductDetailsParams =
QueryProductDetailsParams.newBuilder()
...
.build()
// leverage queryProductDetails Kotlin extension function
val productDetailsResult = withContext(Dispatchers.IO) {
billingClient.queryProductDetails(queryProductDetailsParams)
}
if (productDetailsResult.productDetailsList?.isNotEmpty() == true) {
pd = productDetailsResult.productDetailsList!![0]
}
return pd
}
The problem: The Activity can request prices for different products. The first call works. But all subsequent calls don't: I get back a null. I bump the app and get the same thing again (first call works). Looks like I need to cancel something... Sorry, totally lost. Thank you!
CodePudding user response:
This may not solve your issue, but I think you are missing checking whether the query was successful. If you log the failure case, it will lead you toward a solution.
By the way, you don't need to use withContext
with queryProductDetails()
. I'm pretty sure that's a mistake in the documentation. See here for explanation.
I haven't updated from version 4 to 5, so some of my variable and function names might be wrong in this example. Especially productDetailsResult.result
--I'm just guessing at that. Can't find documentation on their extension functions online.
suspend fun getProductDetails(PitchProductId: Long) : ProductDetails? {
val queryProductDetailsParams =
QueryProductDetailsParams.newBuilder()
...
.build()
val productDetailsResult = billingClient.queryProductDetails(queryProductDetailsParams)
if (productDetailsResult.result.responseCode != BillingResult.OK) {
val resultList = productDetailsResult.productDetailsList.orEmpty()
if (resultList.isNotEmpty() {
return resultList.first()
}
Log.e("MyBilling", "Query product details result was OK but list was empty!")
return null
}
Log.e("MyBilling", "Query product details result was: ${productDetailsResult.result.debugMessage}.")
return null
}
CodePudding user response:
Not an answer, just a working version of Tenfour's comment above ^
// continues from above...
val productDetailsResult =
billingClient.queryProductDetails(queryProductDetailsParams)
Timber.d("PLAY: queryProductDetails rc=%d", productDetailsResult.billingResult.responseCode)
// https://developer.android.com/reference/com/android/billingclient/api/BillingClient.BillingResponseCode
if (productDetailsResult.billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
val resultList = productDetailsResult.productDetailsList.orEmpty()
if (resultList.isNotEmpty()) {
val pd = resultList.first()
Timber.d(
"PLAY: product name is %s at %s",
pd.name,
pd.oneTimePurchaseOfferDetails?.formattedPrice ?: "0.00"
)
return pd
}
}
else if ((productDetailsResult.billingResult.responseCode == BillingClient.BillingResponseCode.SERVICE_DISCONNECTED)) {
Timber.d("PLAY: Service disconnected, reconnecting...")
connect()
return getProductDetails(pitchProductId)
}
...
// etc.