Auto commit (MindMachine) Wed Apr 15 10:01:01 PM CDT 2026
This commit is contained in:
@@ -15,8 +15,8 @@ android {
|
|||||||
applicationId = "solutions.tretter.mindmachine"
|
applicationId = "solutions.tretter.mindmachine"
|
||||||
minSdk = 26
|
minSdk = 26
|
||||||
targetSdk = 35
|
targetSdk = 35
|
||||||
versionCode = 7
|
versionCode = 11
|
||||||
versionName = "1.0.2"
|
versionName = "1.0.6"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
@@ -9,7 +9,8 @@ import com.android.billingclient.api.BillingClientStateListener
|
|||||||
import com.android.billingclient.api.BillingFlowParams
|
import com.android.billingclient.api.BillingFlowParams
|
||||||
import com.android.billingclient.api.BillingResult
|
import com.android.billingclient.api.BillingResult
|
||||||
import com.android.billingclient.api.ProductDetails
|
import com.android.billingclient.api.ProductDetails
|
||||||
import com.android.billingclient.api.ProductDetailsResponseListener
|
import com.android.billingclient.api.QueryProductDetailsResult
|
||||||
|
import com.android.billingclient.api.PendingPurchasesParams
|
||||||
import com.android.billingclient.api.Purchase
|
import com.android.billingclient.api.Purchase
|
||||||
import com.android.billingclient.api.PurchasesResponseListener
|
import com.android.billingclient.api.PurchasesResponseListener
|
||||||
import com.android.billingclient.api.QueryProductDetailsParams
|
import com.android.billingclient.api.QueryProductDetailsParams
|
||||||
@@ -17,6 +18,8 @@ import com.android.billingclient.api.QueryPurchasesParams
|
|||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
|
||||||
class BillingManager(
|
class BillingManager(
|
||||||
context: Context,
|
context: Context,
|
||||||
@@ -44,30 +47,50 @@ class BillingManager(
|
|||||||
handlePurchases(purchases)
|
handlePurchases(purchases)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.enablePendingPurchases()
|
.enablePendingPurchases(
|
||||||
|
PendingPurchasesParams.newBuilder()
|
||||||
|
.enableOneTimeProducts()
|
||||||
|
.build()
|
||||||
|
)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
|
@Volatile
|
||||||
|
private var isConnecting = false
|
||||||
|
|
||||||
fun start() {
|
fun start() {
|
||||||
log("BillingManager.start() - isReady=${billingClient.isReady}")
|
log("BillingManager.start() - isReady=${billingClient.isReady}, isConnecting=$isConnecting")
|
||||||
|
|
||||||
if (billingClient.isReady) {
|
if (billingClient.isReady) {
|
||||||
log("Billing client already ready")
|
log("Billing client already ready")
|
||||||
refresh()
|
refresh()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isConnecting) {
|
||||||
|
log("Billing client connection already in progress")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
isConnecting = true
|
||||||
|
log("Calling startConnection()")
|
||||||
|
|
||||||
billingClient.startConnection(object : BillingClientStateListener {
|
billingClient.startConnection(object : BillingClientStateListener {
|
||||||
override fun onBillingSetupFinished(result: BillingResult) {
|
override fun onBillingSetupFinished(result: BillingResult) {
|
||||||
|
isConnecting = false
|
||||||
log("Billing setup finished: ${result.responseCode} ${result.debugMessage}")
|
log("Billing setup finished: ${result.responseCode} ${result.debugMessage}")
|
||||||
|
|
||||||
if (result.responseCode == BillingClient.BillingResponseCode.OK) {
|
if (result.responseCode == BillingClient.BillingResponseCode.OK) {
|
||||||
|
Handler(Looper.getMainLooper()).post {
|
||||||
refresh()
|
refresh()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
logError("Billing setup failed: ${result.responseCode} ${result.debugMessage}")
|
logError("Billing setup failed: ${result.responseCode} ${result.debugMessage}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBillingServiceDisconnected() {
|
override fun onBillingServiceDisconnected() {
|
||||||
log("Billing service disconnected - attempting reconnect")
|
isConnecting = false
|
||||||
// Auto-reconnection handled by billing client, retry connection
|
log("Billing service disconnected")
|
||||||
start()
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -132,36 +155,52 @@ class BillingManager(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if product details feature is supported
|
|
||||||
val featureResult = billingClient.isFeatureSupported(BillingClient.FeatureType.PRODUCT_DETAILS)
|
val featureResult = billingClient.isFeatureSupported(BillingClient.FeatureType.PRODUCT_DETAILS)
|
||||||
|
log("PRODUCT_DETAILS support: ${featureResult.responseCode} ${featureResult.debugMessage}")
|
||||||
if (featureResult.responseCode != BillingClient.BillingResponseCode.OK) {
|
if (featureResult.responseCode != BillingClient.BillingResponseCode.OK) {
|
||||||
logError("PRODUCT_DETAILS feature not supported: ${featureResult.responseCode}")
|
logError("PRODUCT_DETAILS feature not supported")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val products = listOf(
|
val requestedProducts = listOf(
|
||||||
|
BillingProducts.SUB_REMOVE_ADS_MONTHLY to BillingClient.ProductType.SUBS,
|
||||||
|
BillingProducts.INAPP_REMOVE_ADS_FOREVER to BillingClient.ProductType.INAPP,
|
||||||
|
)
|
||||||
|
|
||||||
|
log("Querying product details for: $requestedProducts")
|
||||||
|
|
||||||
|
val products = requestedProducts.map { (id, type) ->
|
||||||
QueryProductDetailsParams.Product.newBuilder()
|
QueryProductDetailsParams.Product.newBuilder()
|
||||||
.setProductId(BillingProducts.SUB_REMOVE_ADS_MONTHLY)
|
.setProductId(id)
|
||||||
.setProductType(BillingClient.ProductType.SUBS)
|
.setProductType(type)
|
||||||
.build(),
|
.build()
|
||||||
QueryProductDetailsParams.Product.newBuilder()
|
}
|
||||||
.setProductId(BillingProducts.INAPP_REMOVE_ADS_FOREVER)
|
|
||||||
.setProductType(BillingClient.ProductType.INAPP)
|
log(
|
||||||
.build(),
|
"Querying product details for: " +
|
||||||
|
"${BillingProducts.SUB_REMOVE_ADS_MONTHLY}:${BillingClient.ProductType.SUBS}, " +
|
||||||
|
"${BillingProducts.INAPP_REMOVE_ADS_FOREVER}:${BillingClient.ProductType.INAPP}"
|
||||||
)
|
)
|
||||||
|
|
||||||
val params = QueryProductDetailsParams.newBuilder()
|
val params = QueryProductDetailsParams.newBuilder()
|
||||||
.setProductList(products)
|
.setProductList(products)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
billingClient.queryProductDetailsAsync(params, ProductDetailsResponseListener { result, detailsList ->
|
log("Calling queryProductDetailsAsync now")
|
||||||
|
|
||||||
|
billingClient.queryProductDetailsAsync(params) { result, queryResult ->
|
||||||
|
log("queryProductDetails result: ${result.responseCode} ${result.debugMessage}")
|
||||||
|
|
||||||
|
val detailsList = queryResult.productDetailsList
|
||||||
|
log("Fetched products: ${detailsList.map { it.productId }}")
|
||||||
|
|
||||||
|
val unfetched = queryResult.unfetchedProductList
|
||||||
|
log("Unfetched products: ${unfetched.map { "${it.productId}:${it.statusCode}" }}")
|
||||||
|
|
||||||
if (result.responseCode == BillingClient.BillingResponseCode.OK) {
|
if (result.responseCode == BillingClient.BillingResponseCode.OK) {
|
||||||
log("Product details loaded: ${detailsList.size} items")
|
|
||||||
_productDetails.value = detailsList.associateBy { it.productId }
|
_productDetails.value = detailsList.associateBy { it.productId }
|
||||||
} else {
|
|
||||||
logError("queryProductDetails failed: ${result.responseCode} ${result.debugMessage}")
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun queryActivePurchases() {
|
private fun queryActivePurchases() {
|
||||||
|
|||||||
Reference in New Issue
Block a user