Query Subscription Plans in MAUI BillingService Android
Learn to query subscription plans like base1 and base12 in Android using MAUI BillingService and Google Play Billing. Use QueryProductDetailsParams with product ID, not plan IDs, to retrieve details via BillingClient.ProductType.Subs. Step-by-step guide for developers.
How do I properly query subscription plans in Android using MAUI BillingService? I’m able to retrieve the main subscription using BillingClient.ProductType.Subs, but I can’t access the individual plans (base1 and base12) that are defined for the subscription in Google Play Console. What’s the correct way to reference these plans in the QueryProductDetailsParams.Product.Builder?
To properly query subscription plans in Android using MAUI BillingService, you need to understand that Google Play Billing only accepts the subscription product ID in the query, not individual plan IDs. According to the official documentation, you must use the subscription product ID in QueryProductDetailsParams.Product.Builder, then extract the available base plans from the returned ProductDetails object rather than trying to reference individual plan IDs like base1 or base12 directly.
Contents
- Understanding Subscription Plans in Google Play Billing
- The Correct Query Approach
- Retrieving Individual Plans from ProductDetails
- MAUI Implementation Guide
- Code Implementation Example
- Troubleshooting Common Issues
Understanding Subscription Plans in Google Play Billing
When working with Google Play Billing in Android, it’s essential to understand the relationship between subscription products and their base plans. In Google Play Console, a subscription product can have multiple base plans (like base1 for monthly billing and base12 for annual billing), but these plans are not separate product entities.
The Google Play Billing system treats the subscription product as the primary entity, with base plans being attributes of that product. This structure is why you cannot directly reference individual plan IDs in your initial query. When you define a subscription in Google Play Console with multiple pricing options, those options exist as part of the subscription product rather than as standalone products.
The official Google Play Billing documentation emphasizes that the Billing Library only accepts the subscription product ID in queries, not individual plan IDs. This fundamental design principle often causes confusion for developers transitioning from other billing systems.
The Correct Query Approach
The proper method for querying subscription plans involves a two-step process:
- Query the subscription product using its product ID
- Extract the individual plans from the returned ProductDetails
According to Google’s subscription documentation, base plans are not separate product IDs; they belong to the subscription product. You should use the subscription product ID in the query, then read the base-plan list from the returned ProductDetails.
This approach differs from some Microsoft samples that suggest querying each plan individually. While that method can work in certain scenarios, it’s not aligned with Google’s recommended implementation and can lead to inconsistencies in your billing logic.
When setting up your query in QueryProductDetailsParams.Product.Builder, you should specify:
- The subscription product ID (not the plan ID)
- The product type as BillingClient.ProductType.Subs
This ensures you receive complete information about all available base plans for that subscription.
Retrieving Individual Plans from ProductDetails
Once you’ve successfully queried your subscription product, the ProductDetails object will contain all the information about available base plans. Here’s how to access this information:
The ProductDetails object includes SubscriptionOfferDetails, which contains the pricing information for each base plan. The offer ID within these details corresponds to your plan IDs (base1, base12, etc.).
According to the ProductDetails.SubscriptionOfferDetails documentation, each subscription offer includes:
- The offer ID (your base plan identifier)
- Pricing phases information
- Offer tokens required for purchase
This structure allows you to present all available subscription options to users, even though they were retrieved through a single product query. The MAUI BillingService can then use this information to handle purchases for specific plans based on user selection.
MAUI Implementation Guide
When implementing subscription queries in .NET MAUI, you’ll need to create a cross-platform architecture that abstracts the platform-specific billing implementation. The official Microsoft MAUI samples provide a good starting point for this implementation.
For Android specifically, you’ll need to:
- Initialize the BillingClient in your MainActivity or a service
- Create a method to query product details using the subscription product ID
- Process the response to extract individual plan information
- Implement purchase methods that can handle specific plan selection
The cross-platform nature of MAUI means you’ll need to handle platform differences between Android (Google Play Billing), iOS (StoreKit), and Windows (Microsoft Store). The Microsoft cross-platform billing guide explains how to implement this consistently across platforms.
Code Implementation Example
Here’s how to properly implement the subscription query in your MAUI Android project:
// Create the query parameters using subscription product ID (not plan ID)
var productParams = QueryProductDetailsParams.Product.NewBuilder()
.SetProductType(BillingClient.ProductType.Subs)
.SetProductId("my_subscription") // This is your subscription product ID
.Build();
// Build the full query
var queryProductDetailsParams = QueryProductDetailsParams.newBuilder()
.AddProduct(productParams)
.Build();
// Execute the query
billingClient.queryProductDetailsAsync(
queryProductDetailsParams,
new ProductDetailsResponseListener()
{
@Override
public void onProductDetailsResponse(@NonNull ProductDetailsResponse response)
{
if (response.getProductDetailsList().isEmpty())
{
// Handle case where no products were found
return;
}
// Process the product details
foreach (ProductDetails productDetails in response.getProductDetailsList())
{
if (productDetails.getProductType() == BillingClient.ProductType.Subs)
{
// Get all subscription offers (base plans)
List<SubscriptionOfferDetails> offers = productDetails.getSubscriptionOfferDetails();
for (SubscriptionOfferDetails offer : offers)
{
// The offer.getOfferId() will give you "base1", "base12", etc.
String planId = offer.getOfferId();
// Extract pricing information
for (PricingPhase pricingPhase : offer.getPricingPhases().getPricingPhaseList())
{
// Process each pricing phase
}
// Store this information for UI display or purchase handling
}
}
}
}
});
This implementation follows Google’s recommended approach and allows you to access all base plans through a single query.
Troubleshooting Common Issues
When implementing subscription queries in MAUI BillingService, developers often encounter these issues:
-
Querying individual plan IDs: Attempting to use “base1” or “base12” directly in QueryProductDetailsParams.Product.Builder will result in empty responses. Always use the subscription product ID.
-
Missing subscription offers: If your ProductDetails response doesn’t contain expected base plans, verify your subscription configuration in Google Play Console.
-
Platform implementation mismatches: Ensure your Android implementation correctly handles the ProductDetails response before exposing it through your MAUI abstraction layer.
-
Product type confusion: Always use BillingClient.ProductType.Subs for subscriptions, not BillingClient.ProductType.Inapp for in-app purchases.
The community InAppBillingPlugin provides additional examples and troubleshooting guidance for cross-platform billing implementations.
Sources
- Integrate the Google Play Billing Library into your app
- ProductDetails.SubscriptionOfferDetails
- About subscriptions
- .NET MAUI - BillingService - Code Samples
- Implementing Cross-Platform In-App Billing in .NET MAUI Applications
- GitHub - jamesmontemagno/InAppBillingPlugin: Cross-platform In App Billing Plugin for .NET
Conclusion
Querying subscription plans in Android using MAUI BillingService requires using the subscription product ID in your initial query rather than individual plan IDs. By following Google’s recommended approach and extracting base plan information from the ProductDetails response, you can access all available plans like base1 and base12 that are defined in Google Play Console. This method provides a more robust and scalable solution that aligns with Google’s billing system architecture and works effectively within the MAUI cross-platform framework.