Question

Almost all examples of work with remote services contain such code (this one was taken from Google IabHelper)

 mServiceConn = new ServiceConnection() {
        @Override
        public void onServiceDisconnected(ComponentName name) {
            logDebug("Billing service disconnected.");
            mService = null;
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            logDebug("Billing service connected.");
            mService = getServiceFromBinder(service);
            ...
        }
    };

Why the field mService is always set to null? Is it wrong just to ignore onServiceConnected callback? In my experience reconnection usually happens after 1-2 seconds.. Google IABHelper even doesn't check mService for null despite the field is widely used, even is several async methods. And many my users get NPE in case of disconnection. I want to patch IabHelper. The question is how..

What is a proper way to handle disconneсtion when the field mService is used inside async methods? Just ignore onServiceDisconnected and get RemoteExceptions? I thought about wait-notify approach but there is not guarantee that reconnection will happen. Any ideas are welcomed.

Was it helpful?

Solution

The IabHelper example was updated to fix a number of bugs a couple of months ago, so first of all, be sure you have the latest version. I have used an earlier version and made various fixes of my own, so I can't say whether the latest one actually fixes this.

Here is an issue that was filed a while back regarding it:

https://code.google.com/p/android/issues/detail?id=41610

The general approach would be to copy and edit IabHelper, and in your own copy, test for a null value at the top of launchPurchaseFlow(). Something like this:

//If the service has somehow disconnected, then we cannot make the purchase
if(mService == null) {
  result = new IabResult(BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE, 
    "Unable to buy item because billing service disconnected unexpectedly.");
if (listener != null) listener.onIabPurchaseFinished(result, null);
  flagEndAsync();
  return;
}
...

Also, at the end of onServiceDisconnected(), you will want to abort any async operation that may have been interrupted by the disconnection of the service. Something like this:

boolean asyncWasInProgress = mAsyncInProgress;
if(asyncWasInProgress) {
  flagEndAsync();
}

Hope that is helpful. IabHelper (at least the earlier version I used) has a number of bugs and so you can expect to come across this kind of thing, and such problems will need to be fixed when you do.

OTHER TIPS

I refactored the downloaded V3 wrapper class IabHelper of Google to get rid of null pointer exceptions. I don't see an aspect of locking/synchronization problems in my project. There is no parallel processing except when the connection to the Billing service is interrupted, and setting an object to null won't take a long time.

Result can be downloaded from github.

I also felt free to reduce the length of some methods and split them. I'm a fan of the approach that a methods body should not exceed a screen or page; helps to make code more readable.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top