Google published a brand new version to handle the payments in Android but after searching quite a while I cannot find a single example or tutorial from someone who succeeded im
Here is my implementation using billing 2.1.0 in Kotlin. You can easily convert it to Java if you see the whole picture (that's why I'm pasting you the entire activity).
class GoPremiumActivity : AppCompatActivity(), PurchasesUpdatedListener, AcknowledgePurchaseResponseListener {
private lateinit var billingClient: BillingClient
private val skuList = listOf(CStr.PRODUCT_ADS_REMOVE.value)
private var skuDetails: SkuDetails? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.go_premium)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
setupBillingClient()
purchaseButton.setOnClickListener {
val flowParams = BillingFlowParams.newBuilder()
.setSkuDetails(skuDetails)
.build()
billingClient.launchBillingFlow(this@GoPremiumActivity, flowParams)
}
}
private fun setupBillingClient() {
billingClient = BillingClient
.newBuilder(this@GoPremiumActivity)
.enablePendingPurchases()
.setListener(this@GoPremiumActivity)
.build()
billingClient.startConnection(object : BillingClientStateListener {
override fun onBillingSetupFinished(billingResult: BillingResult?) {
if (billingResult?.responseCode == BillingClient.BillingResponseCode.OK) {
getAvailableProducts()
val purchasesResult = billingClient.queryPurchases(BillingClient.SkuType.INAPP)
val purchase = purchasesResult.purchasesList.firstOrNull { it.sku == CStr.PRODUCT_ADS_REMOVE.value}
if (purchase?.isAcknowledged == true) {
Global.prefs.adsRemovalPurchased = true
finish()
}
} else {
showGeneralError()
}
}
override fun onBillingServiceDisconnected() {
/*DO NOTHING*/
}
})
}
fun getAvailableProducts() {
if (billingClient.isReady) {
val params = SkuDetailsParams
.newBuilder()
.setSkusList(skuList)
.setType(BillingClient.SkuType.INAPP)
.build()
billingClient.querySkuDetailsAsync(params) { responseCode, skuDetailsList ->
if (responseCode.responseCode == BillingClient.BillingResponseCode.OK) {
skuDetails = skuDetailsList.firstOrNull()
skuDetails?.let {
purchaseButton.text = String.format("BUY %s", it.price)
showSuccessOrError(success = true)
} ?: run {
showSuccessOrError(success = false)
}
} else {
showGeneralError()
}
}
} else {
showGeneralError()
}
}
override fun onPurchasesUpdated(billingResult: BillingResult?, purchases: MutableList?) {
if (billingResult?.responseCode == BillingClient.BillingResponseCode.OK && purchases != null) {
val purchase = purchases.firstOrNull { it.sku == CStr.PRODUCT_ADS_REMOVE.value}
if (purchase?.purchaseState == Purchase.PurchaseState.PURCHASED) {
if (!purchase.isAcknowledged) {
val acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder()
.setPurchaseToken(purchase.purchaseToken)
.build()
billingClient.acknowledgePurchase(acknowledgePurchaseParams, this@GoPremiumActivity)
}
}
} else if (billingResult?.responseCode == BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED) {
Global.prefs.adsRemovalPurchased = true
finish()
} else {
Global.prefs.adsRemovalPurchased = false
showSuccessOrError(success = true)
}
}
override fun onAcknowledgePurchaseResponse(billingResult: BillingResult?) {
if (billingResult?.responseCode == BillingClient.BillingResponseCode.OK) {
showThankYouDialog(this@GoPremiumActivity)
Global.prefs.adsRemovalPurchased = true
}
}
private fun showSuccessOrError(success: Boolean) {
purchaseProgressBar.visibility = View.GONE
if (success) {
purchaseButton.visibility = View.VISIBLE
} else {
purchaseUnavailable.visibility = View.VISIBLE
}
}
private fun showGeneralError() {
purchaseProgressBar.visibility = View.GONE
purchaseUnavailable.visibility = View.VISIBLE
}
companion object {
fun newIntent(context: Context): Intent {
return Intent(context, GoPremiumActivity::class.java)
}
}
override fun onSupportNavigateUp(): Boolean {
finish()
return true
}
public override fun onDestroy() {
super.onDestroy()
}
override fun onPause() {
super.onPause()
if (isFinishing) {
finish()
}
}
private fun showThankYouDialog(context: Context) {
//Show dialog
}
}
I can remove it if you specifically want it in Java.