I've had in app billing v3 implemented in my app for about a week now. I used a lot of android's sample code to simplify the integration. I've been logging a crash fairly often that I can't seem to reproduce:
Exception Type: java.lang.RuntimeException
Reason: Unable to destroy activity {[package].billing.BillingActivity}: java.lang.IllegalArgumentException: Service not registered: [package].billing.util.IabHelper$1@40646a70
It seems to be breaking on this line:
if (mContext != null) mContext.unbindService(mServiceConn);
I'm binding this service in my onCreate method and disposing it in my onDestroy method (which is where this error is logged). Any pointers?
I just encountered the same issue but on android emulator. Billing v3 requires that Google Play app should be launched at least once and since the emulator lack of Google Play app it cannot set up helper and cannot dispose it in onDestroy().
My personal workaround is just skipping that error in try/catch:
@Override
protected void onDestroy() {
super.onDestroy();
if (bHelper != null){
try {
bHelper.dispose();
}catch (IllegalArgumentException ex){
ex.printStackTrace();
}finally{}
}
bHelper = null;
}
Add this in every onDestroy() where you dispose helper. Works fine for me.
You could replace the line you mentioned:
if (mContext != null) mContext.unbindService(mServiceConn);
by this line
if (mContext != null && mService != null) mContext.unbindService(mServiceConn);
This should do the trick
I checked out the latest version of the sample project and up to today my recommendation is to currently to NOT use IabHelper
. It is massively flawed.
To give you an idea:
1.) the async methods of IabHelper
start a new thread. If IabHelper.dispose()
is called while a thread is running you will always get various exceptions you cannot even handle.
2.) If the connection to the billing service goes down, they set it to null
. But apart from that they never check if mService
is null
before accessing the methods. So it will always crash with NullPointerException
in this case.
public void onServiceDisconnected(ComponentName name) {
logDebug("Billing service disconnected.");
mService = null;
and this is just the tip of the ice berg. Seriously I do not understand how somebody can publish this as reference code.
The IabHelper
class is working in a normal way.
What you need to do is:
when you call startSetup
for the helper, you need to pass a callback IabHelper.OnIabSetupFinishedListener
which will tell you the result of starting setup. If you get failure in the callback, the service connection with the google play services was not established.
You should handle future calls to IabHelper
depending upon the result received in IabHelper.OnIabSetupFinishedListener
. You can surely keep a boolean
field to know what was the status.
The answer sam provided is actually a trick (in his own words). The helper classes aren't supposed to throw exceptions so that the user of those classes can implement some task in such scenarios.
And of-course, try/catch
is best way if you don't want to go in details (whenever anything breaks due to exception, surely first thing which comes in mind is to put that in a try/catch
block).