The Android docs for In-app Billing seem to be pretty clear on the following matter. After the REQUEST_PURCHASE you show the checkout with the pending intent (fine, no problems) then the user interacts with the checkout and hits the buy button (in this case I’m using the static product id android.test.purchased).
Now my broadcast receiver should receive a RESPONSE_CODE and THEN an IN_APP_NOTIFY. Well that’s not happening. Sometimes I get the response first, but frequently I’m getting it after the notification.
The second emphasised section from the Android Doc section quoted below is why this is a problem. If I update the status in my app to pending when I get the async response to the purchase request as the docs seem to indicate I should then if that response comes after the notification my app gets stuck in a pending state. Is it supposed to say “when you receive result_ok from the immediate syncronus response”?
Is it a bug with Goole Play (the Google Play version on my phone is 3.5.15 and the Android os version is 2.2)? Am I misunderstanding the Docs? Are the Docs just plain wrong? Is it an issue with the static testing products? Is something else possibly going wrong? Note that on my side everything is running in the UI thread so it’s not a threading issue.
Log output from a typical non-working run is shown at the botton.
Relevant section of Android documentation (emphasis mine):
Handling broadcast intents
A REQUEST_PURCHASE request also triggers two asynchronous responses
(broadcast intents). First, the Google Play application sends a
RESPONSE_CODE broadcast intent, which provides error information about
the request. If the request does not generate an error, the
RESPONSE_CODE broadcast intent returns RESULT_OK, which indicates that
the request was successfully sent. (To be clear, a RESULT_OK response
does not indicate that the requested purchase was successful; it
indicates that the request was sent successfully to Google Play.)Next, when the requested transaction changes state (for example, the
purchase is successfully charged to a credit card or the user cancels
the purchase), the Google Play application sends an IN_APP_NOTIFY
broadcast intent. This message contains a notification ID, which you
can use to retrieve the transaction details for the REQUEST_PURCHASE
request.Note: The Google Play application also sends an IN_APP_NOTIFY for
refunds. For more information, see Handling IN_APP_NOTIFY messages.Because the purchase process is not instantaneous and can take several
seconds (or more), you must assume that a purchase request is pending
from the time you receive a RESULT_OK message until you receive an
IN_APP_NOTIFY message for the transaction. While the transaction is
pending, the Google Play checkout UI displays an “Authorizing
purchase…” notification; however, this notification is dismissed
after 60 seconds and you should not rely on this notification as your
primary means of conveying transaction status to users. Instead, we
recommend that you do the following:
Example from my logs of things not going in the expected order:
MAKING REQUEST: PurchaseRequest
EXECUTING REQUEST: PurchaseRequest
IMEDIATE RESPONSE IN: PurchaseRequest, IS RESULT_OK
REQUEST ID: 1814990809059790249, PurchaseRequest
Receiver: Notify
Notify String in IN_APP_NOTIFY intent: android.test.purchased
PROCESSING NOTIFICATION
MAKING REQUEST: PurchaseInformationRequest
EXECUTING REQUEST: PurchaseInformationRequest
IMEDIATE RESPONSE IN: PurchaseInformationRequest, IS RESULT_OK
REQUEST ID: 602248989635492868, PurchaseInformationRequest
Receiver: purchase state changed
PROCESSING PURCHASE_STATE_CHANGE
newestMarketPurchaseState = PURCHASED
SetState on product 'Enterprise'. Message: PURCHASED
MAKING REQUEST: ConfirmNotificationsRequest
EXECUTING REQUEST: ConfirmNotificationsRequest
IMEDIATE RESPONSE IN: ConfirmNotificationsRequest, IS RESULT_OK
REQUEST ID: 693394902887436727, ConfirmNotificationsRequest
Receiver: Response Code = RESULT_OK
Receiver: Response Code requestId = 602248989635492868
PROCESSING RESPONSE
ASYNCH RESPONSE IN: PurchaseInformationRequest, IS RESULT_OK
Receiver: Response Code = RESULT_OK
Receiver: Response Code requestId = 1814990809059790249
PROCESSING RESPONSE
ASYNCH RESPONSE IN: PurchaseRequest, IS RESULT_OK
SetState on product 'Enterprise'. Message: PURCHASE PENDING
Receiver: Response Code = RESULT_OK
Receiver: Response Code requestId = 693394902887436727
PROCESSING RESPONSE
ASYNCH RESPONSE IN: ConfirmNotificationsRequest, IS RESULT_OK
Confirm Notifications Request returned asynch OK
I have encountered this very same problem too. According to the answers in the question Are Android broadcasts received in order?, there is no absolute guarantee that the intents will be received in the order they’ve been sent. They usually do, but not necessarily. So even if Google Play orders them correctly, they can still arrive in some other order.
In my opinion, the only solution is not to assume anything about the time when RESPONSE_CODE arrives. In this regard the Android documentation really does seem plain wrong to me. Response codes should’ve probably been implemented through a callback, not as broadcasts. I have to admit that Google sometimes gets rather careless.