Monetization is one of the most important aspects of distributing your product to the rest of the world. It can make or break a small freelance developer or an established startup.
Android, being so widespread, provides ways for users to purchase products from within your app: this is referred to as In-app Billing. Through this set of , developers can offer :
The official documentation is very helpful when it comes to the first steps for adding in-app products to your application. In particular, the is well structured and walks you through each required step:
Let’s focus on the third point.
According to the , we have two ways of testing purchases:
license-test
in the Play Console will be able to make purchases without being actually charged. You can use this when the app goes to QA, or for general testing.Using static responses sounds easy enough, right? You just use one on the following product IDs during a purchase operation:
android.test.purchased
android.test.canceled
android.test.refunded
android.test.item_unavailable
and the Play Store will reply accordingly. The code looks roughly like this:
mService.getBuyIntent(3, "com.example.myapp", "android.test.purchased", PRODUCT_TYPE, developerPayload);
However, if you are testing subscriptions, you’re out of luck:
Note: If you’re testing subscription purchases, you must use the product ID of an actual subscription, not a reserved product ID. []
This means that we cannot rely on static responses to test subscriptions; instead, we need to resort to test purchases.
By using the so-called In-app Billing Sandbox, we can enable access to test purchases. These are the closest thing we have to actual purchases, with a few notable exceptions:
The last point is particularly interesting, because we have two ways of customizing the test purchase behavior.
The first method allows for fine control over the licensing behavior for all the testers: for example, by leaving it to RESPOND_NORMALLY
we have a behavior similar to the real one.
The second method, on the other hand, allows for coarse control over the response of the you can decide whether the card will always approve the purchase or always decline it. Intuitively enough, this second method can be customized by each tester.
In order to be eligible for test purchases, there are a few steps to go through:
Sounds easy enough, right? The documentation is also very encouraging
You religiously follow the documentation, wait 15 minutes (make it 30, just in case), you start testing and…an error occurs. What now?
It turns out that the documentation is fairly optimistic when explaining the required steps for testing in-app purchases. According to , which in turn is a collection of various trial-and-errors by other users, plus my personal experience, there are actually 10+ conditions that you need to meet or account for before being able to properly use test products!
Let’s recap them here:
getBuyIntent
, you’re passing the correct product type, i.e., inapp
if you’re purchasing managed in-app products or subs
if you’re purchasing subscriptions.As you can see, the sandbox is far from straightforward when it comes to real usage, but at least now we have a few extra hints to start looking for a solution!
Bonus tip: faster testing for test subscriptions
We mentioned earlier that test subscriptions have a 1-day expiration period, regardless of their original duration. This means that, even if we cancel the subscription, it will still be considered active for that day. In turn, when the app retrieves the list of purchased products, it will receive the cancelled subscription and present it as an active subscription (because it technically still is). Your UI will then react accordingly and display premium features, instead of the purchase button: again, technically correct, but very inconvenient for us to do quick testing.
However, there’s a nice way of checking whether a subscription’s auto-renewal has been cancelled: the autoRenewing
field inside the INAPP_PURCHASE_DATA
JSON payload that comes from the billing service (see ). When checking the validity of a subscription in a debug environment, you can assume that when autoRenewing
is false
the subscription is cancelled and you can purchase another one.
|