Billing: replace in-app logs with ADB logging, add auto-reconnection
This commit is contained in:
@@ -1256,7 +1256,6 @@ fun RemoveAdsScreen(billingManager: solutions.tretter.mindmachine.billing.Billin
|
||||
val ui by vm.ui.collectAsStateWithLifecycle()
|
||||
val activity = LocalContext.current as? Activity
|
||||
val details by billingManager.productDetails.collectAsStateWithLifecycle()
|
||||
val logs by billingManager.logs.collectAsStateWithLifecycle()
|
||||
|
||||
val subDetails = details[solutions.tretter.mindmachine.billing.BillingProducts.SUB_REMOVE_ADS_MONTHLY]
|
||||
val subPrice = subDetails
|
||||
@@ -1308,21 +1307,6 @@ fun RemoveAdsScreen(billingManager: solutions.tretter.mindmachine.billing.Billin
|
||||
"Note: Purchases only work when the app is installed from Google Play (Internal testing/Production). Debug sideloaded builds won’t complete real billing flows.",
|
||||
color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.8f)
|
||||
)
|
||||
|
||||
// Debug logs
|
||||
Text("Billing logs:", style = MaterialTheme.typography.titleMedium, color = MaterialTheme.colorScheme.onBackground)
|
||||
Column(
|
||||
Modifier
|
||||
.weight(1f)
|
||||
.fillMaxWidth()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.background(MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.2f))
|
||||
.padding(8.dp)
|
||||
) {
|
||||
logs.forEach { log ->
|
||||
Text(log, color = MaterialTheme.colorScheme.onBackground, style = MaterialTheme.typography.bodySmall)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package solutions.tretter.mindmachine.billing
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import com.android.billingclient.api.AcknowledgePurchaseParams
|
||||
import com.android.billingclient.api.BillingClient
|
||||
import com.android.billingclient.api.BillingClientStateListener
|
||||
@@ -16,9 +17,6 @@ import com.android.billingclient.api.QueryPurchasesParams
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
|
||||
class BillingManager(
|
||||
context: Context,
|
||||
@@ -32,15 +30,12 @@ class BillingManager(
|
||||
private val _productDetails = MutableStateFlow<Map<String, ProductDetails>>(emptyMap())
|
||||
val productDetails: StateFlow<Map<String, ProductDetails>> = _productDetails.asStateFlow()
|
||||
|
||||
private val _logs = MutableStateFlow<List<String>>(emptyList())
|
||||
val logs: StateFlow<List<String>> = _logs.asStateFlow()
|
||||
|
||||
private fun log(message: String) {
|
||||
val timestamp = SimpleDateFormat("HH:mm:ss.SSS", Locale.getDefault()).format(Date())
|
||||
_logs.value = _logs.value + "[$timestamp] $message"
|
||||
if (_logs.value.size > 50) {
|
||||
_logs.value = _logs.value.takeLast(50)
|
||||
}
|
||||
Log.d("MindMachineBilling", message)
|
||||
}
|
||||
|
||||
private fun logError(message: String) {
|
||||
Log.e("MindMachineBilling", message)
|
||||
}
|
||||
|
||||
private val billingClient: BillingClient = BillingClient.newBuilder(appContext)
|
||||
@@ -64,12 +59,15 @@ class BillingManager(
|
||||
log("Billing setup finished: ${result.responseCode} ${result.debugMessage}")
|
||||
if (result.responseCode == BillingClient.BillingResponseCode.OK) {
|
||||
refresh()
|
||||
} else {
|
||||
logError("Billing setup failed: ${result.responseCode} ${result.debugMessage}")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBillingServiceDisconnected() {
|
||||
log("Billing service disconnected")
|
||||
// No-op, will retry on next call.
|
||||
log("Billing service disconnected - attempting reconnect")
|
||||
// Auto-reconnection handled by billing client, retry connection
|
||||
start()
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -120,7 +118,11 @@ class BillingManager(
|
||||
.build()
|
||||
|
||||
val result = billingClient.launchBillingFlow(activity, params)
|
||||
log("launchBillingFlow result: ${result.responseCode} ${result.debugMessage}")
|
||||
if (result.responseCode == BillingClient.BillingResponseCode.OK) {
|
||||
log("launchBillingFlow succeeded")
|
||||
} else {
|
||||
logError("launchBillingFlow failed: ${result.responseCode} ${result.debugMessage}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun queryProductDetails() {
|
||||
@@ -146,10 +148,11 @@ class BillingManager(
|
||||
.build()
|
||||
|
||||
billingClient.queryProductDetailsAsync(params, ProductDetailsResponseListener { result, detailsList ->
|
||||
log("queryProductDetails result: ${result.responseCode} ${result.debugMessage}")
|
||||
if (result.responseCode == BillingClient.BillingResponseCode.OK) {
|
||||
_productDetails.value = detailsList.associateBy { it.productId }
|
||||
log("Product details loaded: ${detailsList.size} items")
|
||||
_productDetails.value = detailsList.associateBy { it.productId }
|
||||
} else {
|
||||
logError("queryProductDetails failed: ${result.responseCode} ${result.debugMessage}")
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -162,9 +165,11 @@ class BillingManager(
|
||||
}
|
||||
|
||||
val listener = PurchasesResponseListener { result, purchases ->
|
||||
log("Query purchases result: ${result.responseCode} ${result.debugMessage}")
|
||||
if (result.responseCode == BillingClient.BillingResponseCode.OK) {
|
||||
log("Query purchases returned ${purchases.size} items")
|
||||
handlePurchases(purchases)
|
||||
} else {
|
||||
logError("Query purchases failed: ${result.responseCode} ${result.debugMessage}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,7 +184,7 @@ class BillingManager(
|
||||
}
|
||||
|
||||
private fun handlePurchases(purchases: List<Purchase>) {
|
||||
log("handlePurchases() count=${purchases.size}")
|
||||
log("handlePurchases count=${purchases.size}")
|
||||
val active = purchases.any { p ->
|
||||
p.purchaseState == Purchase.PurchaseState.PURCHASED &&
|
||||
p.products.any { it == BillingProducts.SUB_REMOVE_ADS_MONTHLY || it == BillingProducts.INAPP_REMOVE_ADS_FOREVER }
|
||||
@@ -199,7 +204,13 @@ class BillingManager(
|
||||
val params = AcknowledgePurchaseParams.newBuilder()
|
||||
.setPurchaseToken(purchase.purchaseToken)
|
||||
.build()
|
||||
billingClient.acknowledgePurchase(params) { /* no-op */ }
|
||||
billingClient.acknowledgePurchase(params) { billingResult ->
|
||||
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
|
||||
log("Purchase acknowledged successfully")
|
||||
} else {
|
||||
logError("Failed to acknowledge purchase: ${billingResult.responseCode} ${billingResult.debugMessage}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user