android - onBillingSetupFinished 从未调用过
问题描述
我一直使用 Java,但这次我尝试在 Kotlin 中开发,我有一个应用程序,它有一个支付按钮来删除广告(使用 Google Play 的计费系统),但我无法让它工作。
我已经将我签名的 apk 上传到 Play 管理中心并创建了 ID 为 remove_ads 的产品
这就是我在 AndroidManifest.xml 文件中的
"android.permission.INTERNET"
内容"com.android.vending.BILLING"
在 build.gradle 中:
implementation("com.android.billingclient:billing:4.0.0") implementation("com.android.billingclient:billing-ktx:4.0.0")
在我的 Kotlin 类“设置”中:
创建时:
btnRemoveAds.setOnClickListener {
Toast.makeText(this@Settings, "Click Button", Toast.LENGTH_SHORT).show()
billingClient = BillingClient.newBuilder(this)
.setListener(purchasesUpdatedListener)
.enablePendingPurchases()
.build()
billingClient.startConnection(object : BillingClientStateListener {
override fun onBillingSetupFinished(billingResult: BillingResult) {
Toast.makeText(this@Settings, "SetupFinished", Toast.LENGTH_SHORT).show()
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
Toast.makeText(this@Settings, "OK", Toast.LENGTH_SHORT).show()
// The BillingClient is ready. You can query purchases here.
billingClient.queryPurchasesAsync(
SkuType.INAPP
) { billingResult, list ->
if (list.size != 0){
if (list.get(0).purchaseState == Purchase.PurchaseState.PURCHASED){
setPlus(true)
setResult(RESULT_OK)
} else{
queryAvaliableProducts()
}
} else{
queryAvaliableProducts()
}
}
} else{
Toast.makeText(this@Settings, "NO", Toast.LENGTH_SHORT).show()
}
}
override fun onBillingServiceDisconnected() {
Toast.makeText(this@Settings, "Disconnected", Toast.LENGTH_SHORT).show()
// Try to restart the connection on the next request to
// Google Play by calling the startConnection() method.
}
})
}
按下按钮时我能看到的唯一吐司是“点击按钮”
这些是我的方法:
private fun queryAvaliableProducts() {
val skuList: MutableList<String> = ArrayList()
skuList.add("remove_ads")
val params = SkuDetailsParams.newBuilder()
params.setSkusList(skuList).setType(INAPP)
billingClient.querySkuDetailsAsync(
params.build()
) { billingResult, skuDetailsList -> // Process the result.
if (skuDetailsList!!.size != 0) {
val billingFlowParams = BillingFlowParams.newBuilder()
.setSkuDetails(skuDetailsList[0])
.build()
val responseCode = billingClient.launchBillingFlow(
this@Settings,
billingFlowParams
).responseCode
}
}
}
private val purchasesUpdatedListener =
PurchasesUpdatedListener { billingResult, purchases ->
// To be implemented in a later section.
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK
&& purchases != null
) {
for (purchase in purchases) {
handlePurchase(purchase)
}
} else if (billingResult.responseCode == BillingClient.BillingResponseCode.USER_CANCELED) {
// Handle an error caused by a user cancelling the purchase flow.
} else {
// Handle any other error codes.
}
}
fun handlePurchase(purchase: Purchase) {
if (purchase.purchaseState == Purchase.PurchaseState.PURCHASED) {
if (!purchase.isAcknowledged) {
val acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder()
.setPurchaseToken(purchase.purchaseToken)
.build()
billingClient.acknowledgePurchase(
acknowledgePurchaseParams,
acknowledgePurchaseResponseListener
)
}
}
}
var acknowledgePurchaseResponseListener =
AcknowledgePurchaseResponseListener { billingResult ->
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
setPlus(true)
setResult(RESULT_OK)
finish()
}
}
我还在 billingClient.startConnection 之后实现了一个按钮来检查连接状态
btnConnectionState.setOnClickListener {
Toast.makeText(this@Settings, billingClient.connectionState.toString(), Toast.LENGTH_SHORT).show()
}
结果我得到了 2(已连接),所以我觉得 onBillingSetupFinished 和 onBillingServiceDisconnected 从未被执行很奇怪,我的代码中是否有任何错误?
解决方案
除了 Toast 本身之外,您的代码 afaik 中没有错误。onBillingServiceDisconnected
不在主线程上调用。如果您像这样尝试捕获它:
try {
Toast.makeText(this@Settings, "NO", Toast.LENGTH_SHORT).show()
} catch (ex: Exception) {
Log.e("MyApp", "Error", ex)
}
它会打印这样的错误
06-05 00:00:38.713 8595 9215 E MyApp:java.lang.NullPointerException:无法在未调用 Looper.prepare() 的线程上烤面包
您还可以打印调用回调的线程:
Log.e("MyApp", "Running on ${Thread.currentThread().name}")
它会告诉你
在 PlayBillingLibrary-1 上运行
所以切换回 Toast 的主线程(有办法)或者使用简单的 Log 语句来验证方法是否被调用。
推荐阅读
- android - Android jetpack 如何在另一个链的特定工作任务后启动一个单独的工作管理器链
- c - 我如何在 C 中执行这个 shellcode“ls PathToDirectory > newFile.txt”来创建一个包含目录内容列表的新文件
- prolog - 为什么 Prolog 在过滤列表时会找到很多解决方案?
- laravel - Laravel 5.x - 用于验证 PIN 的自定义中间件
- javascript - 如何在 es6 中创建析构函数
- python - Python Scikit 在 Windows 任务计划程序中学习脚本崩溃
- java - Eclipse 中 Java Maven 模块的行为不一致
- swift - 如何使排序不区分大小写
- python - 批量删除图像中不需要的部分
- flask - Python:在 Synology nas 上作为任务运行我的程序会引发 UnicodeEncodeError