In App Billing v3 IllegalArgumentException using I

2019-02-16 14:39发布

问题:

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?

回答1:

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.



回答2:

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



回答3:

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.



回答4:

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).