使用BillingClient进行应用内计费。ResponceCode = -1。服务连接已断开。

5
在我的应用程序中,我添加了一个捐赠功能(在Google Play上有权限购买的应用程序和下载版本中,此功能正常工作)。我使用了 anjlab 的 easy 库来创建它。我开始更新应用程序,并同时在Kotlin上重新编写了它。由于某种原因,捐赠停止工作。我决定将代码从 anjlab 库改为谷歌的新计费库。但是在尝试购买时,我会得到

responseCode = -1 (服务连接已断开)。

我尝试使用 startConnection(this)恢复连接,尝试更改gradle中的版本,并将新版本加载到库apk中,但旧版和新版都不起作用(如果您从发布的Google Play上下载,则可以正常工作)。代码按照Google的指南编写。我在真实设备上测试了签名应用程序。

SettingsFramgent.kt(只有祭礼代码)

package *

import android.content.Intent
import androidx.preference.PreferenceFragmentCompat
import android.os.Bundle
import android.widget.Toast
import androidx.preference.Preference

import com.starikov.datecalc.R

class SettingsFragment : PreferenceFragmentCompat(), SettingsContract.View {

    private lateinit var presenter: SettingsContract.Presenter

    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
        setPreferencesFromResource(R.xml.preferences, rootKey)

        presenter = SettingsPresenter(activity!!)
        presenter.attachView(this)

val makeDonatePref: Preference = findPreference(MAKE_DONATE_KEY)!!

        makeDonatePref.setOnPreferenceClickListener { presenter.makeDonateClicked(); true }

        presenter.viewIsReady()
    }

    override fun showToast(resId: Int) {
        Toast.makeText(activity, resId, Toast.LENGTH_LONG).show()
    }

    override fun startActivity(intent: Intent) {
        activity!!.startActivity(intent)
    }

    override fun onDestroy() {
        super.onDestroy()
        presenter.detachView()
        if (activity!!.isFinishing) {
            presenter.destroy()
        }
    }

    companion object {
        private const val MAKE_DONATE_KEY = "make_donate"
    }
}

SettingsPresenter.kt

package *

import android.app.Activity
import android.content.ActivityNotFoundException
import android.content.Intent
import android.net.Uri
import com.android.billingclient.api.*

import com.starikov.datecalc.common.PresenterBase
import com.android.billingclient.api.BillingClient
import com.android.billingclient.api.SkuDetailsParams
import com.android.billingclient.api.BillingFlowParams
import com.starikov.datecalc.R
import java.util.*


internal class SettingsPresenter internal constructor(private val activity: Activity)
    : PresenterBase<SettingsContract.View>(), SettingsContract.Presenter {
    private lateinit var billingClient: BillingClient
    private var skuDetailsMap: HashMap<String, SkuDetails> = HashMap()

    override fun makeDonateClicked() {
        initBillingProcessor()
        launchBilling(DONATE_PRODUCT_ID)
    }

    override fun destroy() {
        billingClient.endConnection()
    }

    override fun viewIsReady() {}

    private fun initBillingProcessor() {
        billingClient = BillingClient.newBuilder(activity)
                .enablePendingPurchases()
                .setListener {
            billingResult, purchases ->
            if (billingResult?.responseCode == BillingClient.BillingResponseCode.OK && purchases != null) {
                //purchase done
                view!!.showToast(R.string.thanks_for_donate)
            }
        }.build()

        billingClient.startConnection(object : BillingClientStateListener {
            override fun onBillingSetupFinished(billingResult: BillingResult?) {
                if (billingResult?.responseCode == BillingClient.BillingResponseCode.OK) {
                     // **place of logs**
                    querySkuDetails() 
                }
            }

            override fun onBillingServiceDisconnected() {
                //if wrong
            }
        })
    }

    private fun launchBilling(skuId: String) {
        val billingFlowParams = BillingFlowParams.newBuilder()
                .setSkuDetails(skuDetailsMap[skuId])
                .build()
        billingClient.launchBillingFlow(activity, billingFlowParams)
    }

    private fun querySkuDetails() {
        val skuDetailsParamsBuilder = SkuDetailsParams.newBuilder()
        val skuList = ArrayList<String>()
        skuList.add(DONATE_PRODUCT_ID)
        skuDetailsParamsBuilder.setSkusList(skuList).setType(BillingClient.SkuType.INAPP)
        billingClient.querySkuDetailsAsync(skuDetailsParamsBuilder.build()) { billingResult, skuDetailsList ->
            if (billingResult?.responseCode ==  BillingClient.BillingResponseCode.OK) {
                for (skuDetails in skuDetailsList!!) {
                    skuDetailsMap[skuDetails.sku] = skuDetails
                }
            }
        }
    }

    companion object {
        private const val DONATE_PRODUCT_ID = "donate"
    }
}


在“日志位置”中,我检查到 billingResult.responseCode = -1; debugMessage =“服务连接已断开”。我不知道该怎么办。提前感谢您的帮助。
3个回答

3

在我的情况下,我正在使用懒惰初始化。

这样,在调用launchBillingFlow方法之前,Google结算设置就立即开始了。

这导致服务被断开并且在启动计费流程时还没有准备好。

现在,由于活动的启动,我已经开始BillingClient连接,当用户请求时,流程按预期工作。


2

不确定您是否仍然遇到此问题,但我曾经遇到过。调试显示,计费客户端仍在使用我尚未从旧的com.android.vending包中删除的一些旧AIDL内容。一旦我删除了所有这些代码并清除了应用程序对旧内容的支持,我就能够顺利完成购买而没有错误。


-2
面对这样的问题,我的决定是将其添加到应用程序XML节点中。
<!-- GOOGLE PLAY BILLING -->
    <activity
        android:name="com.android.billingclient.api.ProxyBillingActivity"
        android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
        android:theme="@android:style/Theme.Translucent.NoTitleBar" />

1
这只是一个普通的活动。它有什么独特之处? - Ilya Gazman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接