Reputation: 527
I am implementing a subscription with Google billing in my android application. I have followed Google Play Billing official documentation. I have created subscriptions in Play Console and added relevant functionalities to my application.
The problem is, no subscriptions coming to the app from the Play console, always billingClient!!.queryProductDetailsAsync
method returns an empty productDetailsList
.
Can anyone please help me to identify the problem here?
here is my implementation,
In my app-level gradle file,
implementation "com.android.billingclient:billing-ktx:5.1.0"
In my subscription file
private var billingClient: BillingClient? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//Setup billing
billingSetup()
}
private fun billingSetup() {
billingClient = BillingClient.newBuilder(this)
.setListener(purchasesUpdatedListener)
.enablePendingPurchases()
.build()
//Connect to Google Play
connectToGooglePlay()
}
private fun connectToGooglePlay() {
billingClient!!.startConnection(object : BillingClientStateListener {
override fun onBillingSetupFinished(billingResult: BillingResult) {
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
Log.i("payment_flow", "OnBillingSetupFinish connected")
queryProduct()
} else {
Log.i("payment_flow", "OnBillingSetupFinish failed")
}
}
override fun onBillingServiceDisconnected() {
Log.i("payment_flow", "OnBillingSetupFinish connection lost")
//Re-connect to Google Play
connectToGooglePlay()
}
})
}
private fun queryProduct() {
val productList = ImmutableList.of(
Product.newBuilder()
.setProductId("monthly_plan")
.setProductType(BillingClient.ProductType.SUBS)
.build(),
Product.newBuilder()
.setProductId("yearly_plan")
.setProductType(BillingClient.ProductType.SUBS)
.build()
)
val queryProductDetailsParams = QueryProductDetailsParams.newBuilder()
.setProductList(productList).build()
billingClient!!.queryProductDetailsAsync(queryProductDetailsParams) {
billingResult: BillingResult, productDetailsList: List<ProductDetails> ->
Log.d("payment_flow", "onProductDetailsResponse: 1: $billingResult")
if (productDetailsList.isNotEmpty()) {
tmpProductDetailsList.addAll(productDetailsList)
Log.d("payment_flow", "onProductDetailsResponse: " + productDetailsList.size)
} else {
Log.i("payment_flow", "onProductDetailsResponse: No products")
}
}
}
Subscriptions on the Play Console
Logs when opening the subscriptions page in the app
Thanks in advance
Upvotes: 9
Views: 2919
Reputation: 10155
For anyone else that's coming here from a Google search and not having any luck with the other answers, what finally worked for me was signing the debug build with the release key to match the build that's on Google Play testing track. You probably want to have the version codes match too.
Reference: after multiple days of searching and trying things, I came across this 10-year-old post.
Upvotes: 0
Reputation: 1516
Re-check all configs for your subscriptions and confirm that all of theme opened for right regions.
Upvotes: 0
Reputation: 141
For me the problem was i just created the subscription in google play console. there was 2 base plans, one weekly and one monthly. it was returning the weekly details not the montly. after so much searching in the code i thought maybe it takes time for newly created subscription, turns out google caches the products in your device. i selected the Google play app on my device and in the app info page i just selected the "Clear data" so all cached data was cleared and now it works just fine and returns all the products.
Upvotes: 9
Reputation: 1255
Ok my issue was that my products were not showing up in my UI so I surrounded my looping and displaying of my products in a thread. Below is my code, hope it helps. Other than that, your code looks the same as mine. So key point, runOnUiThread
. My products are loading perfectly now and can purchase.
billingClient.queryProductDetailsAsync(
params,
(billingResult, productDetailsList) -> {
// Process the result
Log.d(TAG,"Got list queryProductDetailsAsync "+productDetailsList.size());
for (ProductDetails productDetails : productDetailsList){
Log.d(TAG,"Got productDetails: "+productDetails.getName()+"\nDesc: "+productDetails.getDescription());
String productName = productDetails.getName();
String productPrice = productDetails.getSubscriptionOfferDetails().get(0)
.getPricingPhases().getPricingPhaseList().get(0).getFormattedPrice();
String productID = productDetails.getProductId().toString();
runOnUiThread(new Runnable() {
@Override
public void run() {
if (productDetails.getProductId().equals(Subscriptions.MONTHLY)) {
Log.d(TAG,"Got product Subscriptions.MONTHLY");
cvMonth.setVisibility(View.VISIBLE);
tvTitleMonth.setText(productName+"\n"+productPrice);
tvDescMonth.setText(productDetails.getDescription());
btnBuyMonth.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
launchPurchaseFlow(productDetails);
}
});
}
if (productDetails.getProductId().equals(Subscriptions.BI_ANNUAL)) {
Log.d(TAG,"Got product Subscriptions.BI_ANNUAL");
cvSixMonth.setVisibility(View.VISIBLE);
tvTitleSixMonth.setText(productName+"\n"+productPrice);
tvDescSixMonth.setText(productDetails.getDescription()
+"\nYou save 40% compared to Monthly Subscription");
btnBuySixMonth.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
launchPurchaseFlow(productDetails);
}
});
}
if (productDetails.getProductId().equals(Subscriptions.ANNUAL)) {
Log.d(TAG,productName+"\n"+productPrice);
cvAnnual.setVisibility(View.VISIBLE);
tvTitleAnnual.setText(productName+"\n"+productPrice);
tvDescAnnual.setText(productDetails.getDescription()
+"\nYou save 40% compared to Monthly Subscription. Only " +
"pay once a year.");
btnBuyAnnual.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
launchPurchaseFlow(productDetails);
}
});
}
if(loadingDialog != null){
loadingDialog.dismiss();
}
}
});
}
}
);
Upvotes: 0