Mark
Mark

Reputation: 3748

How to get multiple product details from Google Play Billing 5?

How do you query a list of products from google play billing 5?

From https://developer.android.com/google/play/billing/integrate#java, we query the details of a single product by passing the name of the product to setProductId,

QueryProductDetailsParams queryProductDetailsParams =
    QueryProductDetailsParams.newBuilder()
        .setProductList(
            ImmutableList.of(
                Product.newBuilder()
                    .setProductId("product_id_example")
                    .setProductType(ProductType.SUBS)
                    .build()))
        .build();

billingClient.queryProductDetailsAsync(
    queryProductDetailsParams,
    new ProductDetailsResponseListener() {
        public void onProductDetailsResponse(BillingResult billingResult,
                List<ProductDetails> productDetailsList) {
            // check billingResult
            // process returned productDetailsList
        }
    }
)

But that only gets a single product, thus when you try to print out List<ProductDetails> productDetailsList there is only one. So how do you pass in multiple products?

As far as I am aware .setProductId("product_id_example") only takes a string and not a list.

Upvotes: 7

Views: 3970

Answers (4)

Mehul Patel
Mehul Patel

Reputation: 11

To query a list of products from Google Play Billing Library version 5 (or later), you typically use the QueryProductDetailsParams method. Here's a general overview of how you can do this:

val productList = ArrayList<QueryProductDetailsParams.Product>()
productList.add(QueryProductDetailsParams.Product.newBuilder()
    .setProductId(Constants.BASE_PLAN)
    .setProductType(SUBS)
    .build()
)

productList.add(QueryProductDetailsParams.Product.newBuilder()
    .setProductId(Constants.STANDER_PLAN)
    .setProductType(SUBS)
    .build()
)

Upvotes: 0

loseyk
loseyk

Reputation: 1

You just use MutableList to make it easy

val productList : MutableList<QueryProductDetailsParams.Product> = arrayListOf()
for (product in LIST_OF_PRODUCTS) {
    productList.add(
        QueryProductDetailsParams.Product.newBuilder()
            .setProductId(product)
            .setProductType(BillingClient.ProductType.SUBS)
            .build()
    )
}
private val LIST_OF_PRODUCTS = listOf(
            "basic_subscription",
            "premium_subscription"
        )

Upvotes: 0

Tyler V
Tyler V

Reputation: 10940

The official examples use an ImmutableList for some reason to build the query, but you don't actually need to use that. The setProductList method just takes List<Product> as its input, it does not require ImmutableList.

You could use something like this (API 24+ to use stream()):

List<String> ids = Arrays.asList("1","2","3"); // your product IDs

List<Product> productList = ids.stream().map( productId -> 
    Product.newBuilder()
           .setProductId(productId)
           .setProductType(BillingClient.ProductType.SUBS)
           .build()
).collect(Collectors.toList());

QueryProductDetailsParams params = QueryProductDetailsParams.newBuilder()
        .setProductList(productList)
        .build();

If you have API < 24, you could just make an ArrayList instead.

List<String> ids = Arrays.asList("1","2","3"); // your product IDs

ArrayList<Product> productList = new ArrayList<>();
for(String productId : ids) {
    productList.add(
        Product.newBuilder()
            .setProductId(productId)
            .setProductType(BillingClient.ProductType.SUBS)
            .build()
    );
}

QueryProductDetailsParams params = QueryProductDetailsParams.newBuilder()
        .setProductList(productList)
        .build();

I suspect they wrote the example in Kotlin (using listOf), and automatically converted it to Java (somehow giving us ImmutableList.of)...

Upvotes: 5

Mark
Mark

Reputation: 3748

Looks like a good answer can be found here: Adding multiple products to productlist for queryProductDetailsAsync in android billing 5.0.0

But I'll provide some comments below:

To add additional products we need to have the products in the immutableList, so without a for-loop we can just have:

QueryProductDetailsParams queryProductDetailsParams = QueryProductDetailsParams.newBuilder()
                .setProductList(
                        ImmutableList.of(
                                QueryProductDetailsParams.Product.newBuilder()
                                        .setProductId("Product1")
                                        .setProductType(BillingClient.ProductType.INAPP)
                                        .build(),
                                QueryProductDetailsParams.Product.newBuilder()
                                        .setProductId("Product2")
                                        .setProductType(BillingClient.ProductType.INAPP)
                                        .build()
                )).build();

However, that isn't suitable if your products need to be populated dynamically. This means we need to dynamically populate the items within the ImmutableList. You'll notice that the add method for ImmutableList is deprecated so the add method does nothing.

As a work around, I created an ArrayList, populate the products into the ArrayList and then cast it to an ImmutableList

ImmutableList<QueryProductDetailsParams.Product> productsList = ImmutableList.of();
ArrayList<QueryProductDetailsParams.Product> products = new ArrayList();
for (String productId : productIds ) {
    products.add(QueryProductDetailsParams.Product.newBuilder()
            .setProductId(productId)
            .setProductType(BillingClient.ProductType.INAPP)
            .build());
}

productsList = ImmutableList.copyOf(products);

QueryProductDetailsParams queryProductDetailsParams = QueryProductDetailsParams.newBuilder()
                .setProductList(productsList).build();

Upvotes: 4

Related Questions