Migrated to Play billing v4

This commit is contained in:
Prathamesh More 2021-11-08 11:08:52 +05:30
parent 824e77f59b
commit 5fa3b8febc
4 changed files with 52 additions and 136 deletions

View file

@ -154,7 +154,7 @@ dependencies {
implementation 'org.eclipse.mylyn.github:org.eclipse.egit.github.core:2.1.5' implementation 'org.eclipse.mylyn.github:org.eclipse.egit.github.core:2.1.5'
implementation 'com.github.AdrienPoupa:jaudiotagger:2.2.3' implementation 'com.github.AdrienPoupa:jaudiotagger:2.2.3'
implementation 'com.anjlab.android.iab.v3:library:1.1.0' implementation 'com.anjlab.android.iab.v3:library:2.0.0'
implementation 'com.r0adkll:slidableactivity:2.1.0' implementation 'com.r0adkll:slidableactivity:2.1.0'
implementation 'com.heinrichreimersoftware:material-intro:2.0.0' implementation 'com.heinrichreimersoftware:material-intro:2.0.0'
implementation 'com.github.dhaval2404:imagepicker:1.7.1' implementation 'com.github.dhaval2404:imagepicker:1.7.1'

View file

@ -21,7 +21,7 @@ import code.name.monkey.appthemehelper.util.VersionUtils
import code.name.monkey.retromusic.Constants.PRO_VERSION_PRODUCT_ID import code.name.monkey.retromusic.Constants.PRO_VERSION_PRODUCT_ID
import code.name.monkey.retromusic.appshortcuts.DynamicShortcutManager import code.name.monkey.retromusic.appshortcuts.DynamicShortcutManager
import com.anjlab.android.iab.v3.BillingProcessor import com.anjlab.android.iab.v3.BillingProcessor
import com.anjlab.android.iab.v3.TransactionDetails import com.anjlab.android.iab.v3.PurchaseInfo
import org.koin.android.ext.koin.androidContext import org.koin.android.ext.koin.androidContext
import org.koin.core.context.startKoin import org.koin.core.context.startKoin
@ -52,7 +52,7 @@ class App : Application() {
billingProcessor = BillingProcessor( billingProcessor = BillingProcessor(
this, BuildConfig.GOOGLE_PLAY_LICENSING_KEY, this, BuildConfig.GOOGLE_PLAY_LICENSING_KEY,
object : BillingProcessor.IBillingHandler { object : BillingProcessor.IBillingHandler {
override fun onProductPurchased(productId: String, details: TransactionDetails?) {} override fun onProductPurchased(productId: String, details: PurchaseInfo?) {}
override fun onPurchaseHistoryRestored() { override fun onPurchaseHistoryRestored() {
Toast.makeText( Toast.makeText(

View file

@ -14,10 +14,8 @@
*/ */
package code.name.monkey.retromusic.activities package code.name.monkey.retromusic.activities
import android.content.Intent
import android.content.res.ColorStateList import android.content.res.ColorStateList
import android.graphics.Color import android.graphics.Color
import android.os.AsyncTask
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.MenuItem import android.view.MenuItem
@ -31,14 +29,12 @@ import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.activities.base.AbsBaseActivity import code.name.monkey.retromusic.activities.base.AbsBaseActivity
import code.name.monkey.retromusic.databinding.ActivityProVersionBinding import code.name.monkey.retromusic.databinding.ActivityProVersionBinding
import com.anjlab.android.iab.v3.BillingProcessor import com.anjlab.android.iab.v3.BillingProcessor
import com.anjlab.android.iab.v3.TransactionDetails import com.anjlab.android.iab.v3.PurchaseInfo
import java.lang.ref.WeakReference
class PurchaseActivity : AbsBaseActivity(), BillingProcessor.IBillingHandler { class PurchaseActivity : AbsBaseActivity(), BillingProcessor.IBillingHandler {
private lateinit var binding: ActivityProVersionBinding private lateinit var binding: ActivityProVersionBinding
private lateinit var billingProcessor: BillingProcessor private lateinit var billingProcessor: BillingProcessor
private var restorePurchaseAsyncTask: AsyncTask<*, *, *>? = null
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
setDrawUnderStatusBar() setDrawUnderStatusBar()
@ -58,10 +54,8 @@ class PurchaseActivity : AbsBaseActivity(), BillingProcessor.IBillingHandler {
MaterialUtil.setTint(binding.purchaseButton, true) MaterialUtil.setTint(binding.purchaseButton, true)
binding.restoreButton.setOnClickListener { binding.restoreButton.setOnClickListener {
if (restorePurchaseAsyncTask == null || restorePurchaseAsyncTask!!.status != AsyncTask.Status.RUNNING) {
restorePurchase() restorePurchase()
} }
}
binding.purchaseButton.setOnClickListener { binding.purchaseButton.setOnClickListener {
billingProcessor.purchase(this@PurchaseActivity, PRO_VERSION_PRODUCT_ID) billingProcessor.purchase(this@PurchaseActivity, PRO_VERSION_PRODUCT_ID)
} }
@ -70,13 +64,25 @@ class PurchaseActivity : AbsBaseActivity(), BillingProcessor.IBillingHandler {
} }
private fun restorePurchase() { private fun restorePurchase() {
if (restorePurchaseAsyncTask != null) { Toast.makeText(this, R.string.restoring_purchase, Toast.LENGTH_SHORT)
restorePurchaseAsyncTask!!.cancel(false) .show()
} billingProcessor.loadOwnedPurchasesFromGoogleAsync(object :
restorePurchaseAsyncTask = RestorePurchaseAsyncTask(this).execute() BillingProcessor.IPurchasesResponseListener {
override fun onPurchasesSuccess() {
onPurchaseHistoryRestored()
} }
override fun onProductPurchased(productId: String, details: TransactionDetails?) { override fun onPurchasesError() {
Toast.makeText(
this@PurchaseActivity,
R.string.could_not_restore_purchase,
Toast.LENGTH_SHORT
).show()
}
})
}
override fun onProductPurchased(productId: String, details: PurchaseInfo?) {
Toast.makeText(this, R.string.thank_you, Toast.LENGTH_SHORT).show() Toast.makeText(this, R.string.thank_you, Toast.LENGTH_SHORT).show()
setResult(RESULT_OK) setResult(RESULT_OK)
} }
@ -103,12 +109,6 @@ class PurchaseActivity : AbsBaseActivity(), BillingProcessor.IBillingHandler {
binding.purchaseButton.isEnabled = true binding.purchaseButton.isEnabled = true
} }
public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (!billingProcessor.handleActivityResult(requestCode, resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data)
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) { when (item.itemId) {
android.R.id.home -> finish() android.R.id.home -> finish()
@ -121,52 +121,6 @@ class PurchaseActivity : AbsBaseActivity(), BillingProcessor.IBillingHandler {
super.onDestroy() super.onDestroy()
} }
private class RestorePurchaseAsyncTask(purchaseActivity: PurchaseActivity) :
AsyncTask<Void, Void, Boolean>() {
private val buyActivityWeakReference: WeakReference<PurchaseActivity> = WeakReference(
purchaseActivity
)
override fun onPreExecute() {
super.onPreExecute()
val purchaseActivity = buyActivityWeakReference.get()
if (purchaseActivity != null) {
Toast.makeText(purchaseActivity, R.string.restoring_purchase, Toast.LENGTH_SHORT)
.show()
} else {
cancel(false)
}
}
override fun doInBackground(vararg params: Void): Boolean? {
val purchaseActivity = buyActivityWeakReference.get()
if (purchaseActivity != null) {
return purchaseActivity.billingProcessor.loadOwnedPurchasesFromGoogle()
}
cancel(false)
return null
}
override fun onPostExecute(b: Boolean?) {
super.onPostExecute(b)
val purchaseActivity = buyActivityWeakReference.get()
if (purchaseActivity == null || b == null) {
return
}
if (b) {
purchaseActivity.onPurchaseHistoryRestored()
} else {
Toast.makeText(
purchaseActivity,
R.string.could_not_restore_purchase,
Toast.LENGTH_SHORT
).show()
}
}
}
companion object { companion object {
private const val TAG: String = "PurchaseActivity" private const val TAG: String = "PurchaseActivity"
} }

View file

@ -14,9 +14,7 @@
*/ */
package code.name.monkey.retromusic.activities package code.name.monkey.retromusic.activities
import android.content.Intent
import android.graphics.Paint import android.graphics.Paint
import android.os.AsyncTask
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
@ -27,6 +25,7 @@ import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import androidx.annotation.LayoutRes import androidx.annotation.LayoutRes
import androidx.appcompat.widget.AppCompatImageView import androidx.appcompat.widget.AppCompatImageView
import androidx.core.view.isVisible
import androidx.recyclerview.widget.DefaultItemAnimator import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@ -41,9 +40,8 @@ import code.name.monkey.retromusic.databinding.ActivityDonationBinding
import code.name.monkey.retromusic.extensions.textColorPrimary import code.name.monkey.retromusic.extensions.textColorPrimary
import code.name.monkey.retromusic.extensions.textColorSecondary import code.name.monkey.retromusic.extensions.textColorSecondary
import com.anjlab.android.iab.v3.BillingProcessor import com.anjlab.android.iab.v3.BillingProcessor
import com.anjlab.android.iab.v3.PurchaseInfo
import com.anjlab.android.iab.v3.SkuDetails import com.anjlab.android.iab.v3.SkuDetails
import com.anjlab.android.iab.v3.TransactionDetails
import java.lang.ref.WeakReference
import java.util.* import java.util.*
class SupportDevelopmentActivity : AbsBaseActivity(), BillingProcessor.IBillingHandler { class SupportDevelopmentActivity : AbsBaseActivity(), BillingProcessor.IBillingHandler {
@ -53,11 +51,9 @@ class SupportDevelopmentActivity : AbsBaseActivity(), BillingProcessor.IBillingH
companion object { companion object {
val TAG: String = SupportDevelopmentActivity::class.java.simpleName val TAG: String = SupportDevelopmentActivity::class.java.simpleName
const val DONATION_PRODUCT_IDS = R.array.donation_ids const val DONATION_PRODUCT_IDS = R.array.donation_ids
private const val TEZ_REQUEST_CODE = 123
} }
var billingProcessor: BillingProcessor? = null var billingProcessor: BillingProcessor? = null
private var skuDetailsLoadAsyncTask: AsyncTask<*, *, *>? = null
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == android.R.id.home) { if (item.itemId == android.R.id.home) {
@ -99,13 +95,35 @@ class SupportDevelopmentActivity : AbsBaseActivity(), BillingProcessor.IBillingH
} }
private fun loadSkuDetails() { private fun loadSkuDetails() {
if (skuDetailsLoadAsyncTask != null) { binding.progressContainer.isVisible = true
skuDetailsLoadAsyncTask!!.cancel(false) binding.recyclerView.isVisible = false
} val ids =
skuDetailsLoadAsyncTask = SkuDetailsLoadAsyncTask(this).execute() resources.getStringArray(DONATION_PRODUCT_IDS)
billingProcessor!!.getPurchaseListingDetailsAsync(
ArrayList(listOf(*ids)),
object : BillingProcessor.ISkuDetailsResponseListener {
override fun onSkuDetailsResponse(skuDetails: MutableList<SkuDetails>?) {
if (skuDetails == null || skuDetails.isEmpty()) {
binding.progressContainer.isVisible = false
return
} }
override fun onProductPurchased(productId: String, details: TransactionDetails?) { binding.progressContainer.isVisible = false
binding.recyclerView.apply {
itemAnimator = DefaultItemAnimator()
layoutManager = GridLayoutManager(this@SupportDevelopmentActivity, 2)
adapter = SkuDetailsAdapter(this@SupportDevelopmentActivity, skuDetails)
isVisible = true
}
}
override fun onSkuDetailsError(error: String?) {
Log.e(TAG, error.toString())
}
})
}
override fun onProductPurchased(productId: String, details: PurchaseInfo?) {
// loadSkuDetails(); // loadSkuDetails();
Toast.makeText(this, R.string.thank_you, Toast.LENGTH_SHORT).show() Toast.makeText(this, R.string.thank_you, Toast.LENGTH_SHORT).show()
} }
@ -119,68 +137,12 @@ class SupportDevelopmentActivity : AbsBaseActivity(), BillingProcessor.IBillingH
Toast.makeText(this, R.string.restored_previous_purchases, Toast.LENGTH_SHORT).show() Toast.makeText(this, R.string.restored_previous_purchases, Toast.LENGTH_SHORT).show()
} }
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (!billingProcessor!!.handleActivityResult(requestCode, resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data)
}
if (requestCode == TEZ_REQUEST_CODE) {
// Process based on the data in response.
// Log.d("result", data!!.getStringExtra("Status"))
}
}
override fun onDestroy() { override fun onDestroy() {
billingProcessor?.release() billingProcessor?.release()
skuDetailsLoadAsyncTask?.cancel(true)
super.onDestroy() super.onDestroy()
} }
} }
private class SkuDetailsLoadAsyncTask(supportDevelopmentActivity: SupportDevelopmentActivity) :
AsyncTask<Void, Void, List<SkuDetails>>() {
private val weakReference: WeakReference<SupportDevelopmentActivity> = WeakReference(
supportDevelopmentActivity
)
override fun onPreExecute() {
super.onPreExecute()
val supportDevelopmentActivity = weakReference.get() ?: return
supportDevelopmentActivity.binding.progressContainer.visibility = View.VISIBLE
supportDevelopmentActivity.binding.recyclerView.visibility = View.GONE
}
override fun doInBackground(vararg params: Void): List<SkuDetails>? {
val dialog = weakReference.get()
if (dialog != null) {
val ids =
dialog.resources.getStringArray(SupportDevelopmentActivity.DONATION_PRODUCT_IDS)
return dialog.billingProcessor!!.getPurchaseListingDetails(ArrayList(Arrays.asList(*ids)))
}
cancel(false)
return null
}
override fun onPostExecute(skuDetails: List<SkuDetails>?) {
super.onPostExecute(skuDetails)
val dialog = weakReference.get() ?: return
if (skuDetails == null || skuDetails.isEmpty()) {
dialog.binding.progressContainer.visibility = View.GONE
return
}
dialog.binding.progressContainer.visibility = View.GONE
dialog.binding.recyclerView.apply {
itemAnimator = DefaultItemAnimator()
layoutManager = GridLayoutManager(dialog, 2)
adapter = SkuDetailsAdapter(dialog, skuDetails)
visibility = View.VISIBLE
}
}
}
class SkuDetailsAdapter( class SkuDetailsAdapter(
private var donationsDialog: SupportDevelopmentActivity, private var donationsDialog: SupportDevelopmentActivity,
objects: List<SkuDetails> objects: List<SkuDetails>
@ -221,7 +183,7 @@ class SkuDetailsAdapter(
viewHolder.title.text = skuDetails.title.replace("Music Player - MP3 Player - Retro", "") viewHolder.title.text = skuDetails.title.replace("Music Player - MP3 Player - Retro", "")
.trim { it <= ' ' } .trim { it <= ' ' }
viewHolder.text.text = skuDetails.description viewHolder.text.text = skuDetails.description
viewHolder.text.visibility = View.GONE viewHolder.text.isVisible = false
viewHolder.price.text = skuDetails.priceText viewHolder.price.text = skuDetails.priceText
viewHolder.image.setImageResource(getIcon(i)) viewHolder.image.setImageResource(getIcon(i))