Reputation: 200
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.
Upvotes: 3
Views: 337
Reputation: 11
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.
Upvotes: 0
Reputation: 15605
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.
Upvotes: 2