迁移至Play Billing Library 6时setOfferToken触发空指针异常求助
迁移至Play Billing Library 6后订阅功能无法正常工作
我正在迁移至Play Billing Library 6,应用内购买功能已成功实现,但订阅功能无法正常工作。订阅功能必须使用setOfferToken参数,我的代码如下:
class AccessAllActivity: AppCompatActivity() { private lateinit var binding: ActivityAccessAllBinding private lateinit var billingClient: BillingClient private lateinit var productDetails: ProductDetails private val onBackPressedCallback: OnBackPressedCallback = object: OnBackPressedCallback(true) { override fun handleOnBackPressed() { backPress() } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) onBackPressedDispatcher.addCallback(this, onBackPressedCallback) binding = ActivityAccessAllBinding.inflate(layoutInflater) setContentView(binding.root) billingClient = BillingClient.newBuilder(this) .setListener(purchasesUpdatedListener) .enablePendingPurchases() .build() billingClient.startConnection(object: BillingClientStateListener { override fun onBillingSetupFinished(billingResult: BillingResult) { if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) { Log.d(TAG, "Billing response OK") queryPurchases() queryAvailableProducts() } else { Log.e(TAG, billingResult.debugMessage) } } override fun onBillingServiceDisconnected() { Log.i(TAG, "Billing connection disconnected") } }) binding.btnClose.setOnClickListener { backPress() } binding.btnSubscribeNow.setOnClickListener { startSub() } } fun queryPurchases() { if (!billingClient.isReady) { Log.e(TAG, "queryPurchases: BillingClient is not ready") } billingClient.queryPurchasesAsync( QueryPurchasesParams.newBuilder().setProductType(BillingClient.ProductType.SUBS).build() ) { billingResult, _ -> if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) { /*if (purchaseList.isNotEmpty()) { //_purchases.value = purchaseList } else { //_purchases.value = emptyList() }*/ } else { Log.e(TAG, billingResult.debugMessage) } } } private fun queryAvailableProducts() { val subProductList = listOf( Product.newBuilder() .setProductId("subscription") .setProductType(BillingClient.ProductType.SUBS) .build(), ) val subParams = QueryProductDetailsParams.newBuilder().setProductList(subProductList).build() billingClient.queryProductDetailsAsync(subParams) { billingResult, productDetailsList -> if (billingResult.responseCode == BillingClient.BillingResponseCode.OK && productDetailsList.isNotEmpty()) { val appSubProduct = productDetailsList.find { p-> p.productId == "subscription" } if (appSubProduct != null) { startSub() } } } } private fun startSub() { if (!productDetails.subscriptionOfferDetails.isNullOrEmpty()) { val productDetailsParamsList = listOf( ProductDetailsParams.newBuilder() .setProductDetails(productDetails) .setOfferToken(productDetails.subscriptionOfferDetails!!.first().offerToken) .build() ) val billingFlowParams = BillingFlowParams.newBuilder() .setProductDetailsParamsList(productDetailsParamsList) .build() billingClient.launchBillingFlow(this, billingFlowParams) } else { println("Check productDetails, because is null") } } private val purchasesUpdatedListener = PurchasesUpdatedListener { billingResult, purchases -> if (billingResult.responseCode == BillingClient.BillingResponseCode.OK && purchases != null) { for (purchase in purchases) { handlePurchase(purchase) } } else if (billingResult.responseCode == BillingClient.BillingResponseCode.USER_CANCELED) { Toast.makeText(this, string.payment_cancelled, Toast.LENGTH_LONG).show() } else { Toast.makeText(this, string.payment_error, Toast.LENGTH_LONG).show() Log.i(TAG, "Billing service error ${billingResult.responseCode}") } } private fun handlePurchase(purchase: Purchase) { if (purchase.purchaseState == Purchase.PurchaseState.PURCHASED) { val consumeParams = ConsumeParams.newBuilder() .setPurchaseToken(purchase.purchaseToken) .build() billingClient.consumeAsync(consumeParams) { _, _ -> finish() } } else if (purchase.purchaseState == Purchase.PurchaseState.PENDING) { Toast.makeText(this, string.payment_error, Toast.LENGTH_LONG).show() } } override fun onDestroy() { super.onDestroy() billingClient.endConnection() } private fun backPress() { finish() } companion object { private const val TAG = "ActivityAccessAll" } }
我已查阅官方文档及StackOverflow上的相关解答,但仍无法定位问题所在,恳请各位提供帮助。
内容的提问来源于stack exchange,提问作者Lanuwapangla
相关产品推荐
相关产品推荐

