On Android we have a class that wraps a LocationClient object from GMS (Google Mobile Services). (Note that LocationClient implements com.google.android.gms.common.GooglePlayServicesClient).
Unfortunately the LocationClient object has a habit of throwing DeadObjectExceptions (e.g. when we invoke locationClient.getLastLocation()), which we detect through several of our logging mechanisms. What's weird, however, is that LocationClient isn't documented as throwing DeadObjectExceptions, and furthermore I'm only able to catch said DeadObjectExceptions ~ 1/40th of the time they occur o_0. We have no repro for this issue and I've personally never seen it, however it occurs for a large number of our users.
Other notes:
[a] what is the line "Caused by: java.lang.IllegalStateException: android.os.DeadObjectException" about? Those two Exceptions types do not have an ancestor-descendant relationship
[b] I posted to the Android forum, but of course they rejected my post as 'wrong forum,' and there's no GMS forum so I'm totally out of luck.
In summary, the question is: GMS is triggering this oddly uncatchable exception, so what's up with that and what can I do?
Here's a stack trace:
com.myapp.android.service.AsyncExecutionException
at com.myapp.android.service.AsyncService$ExceptionThrower.run(MyApp:120)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4794)
at java.lang.reflect.Method.invokeNative(Method.java)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:556)
at dalvik.system.NativeStart.main(NativeStart.java)
Caused by: java.lang.IllegalStateException: android.os.DeadObjectException
at com.google.android.gms.internal.ey.getLastLocation()
at com.google.android.gms.internal.ez.getLastLocation()
at com.google.android.gms.location.LocationClient.getLastLocation()
***at com.myapp.GoogleLocationProvider.getLastLocation(MyApp:92)***
at com.myapp.LocationProducer.getLocation(MyApp:183)
at com.myapp.LocationProducer.getLocationHeader(MyApp:194)
at com.myapp.API.onExecute(MyApp:344)
...
at java.lang.Thread.run(Thread.java:856)
Caused by: android.os.DeadObjectException
at android.os.BinderProxy.transact(Binder.java)
at com.google.android.gms.internal.ex$a$a.a()
at com.google.android.gms.internal.ey.getLastLocation()
at com.google.android.gms.internal.ez.getLastLocation()
***at com.google.android.gms.location.LocationClient.getLastLocation()***
at com.myapp.GoogleLocationProvider.getLastLocation(MyApp:92)
at com.myapp.LocationProducer.getLocation(MyApp:183)
at com.myapp.LocationProducer.getLocationHeader(MyApp:194)
...
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
at java.util.concurrent.FutureTask.run(FutureTask.java:137)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
at java.lang.Thread.run(Thread.java:856)
------------ ADDENDUM ------------- Here is our actual code. You'll notice we always check whether mLocationClient.isConnected() beforehand, so that's not the issue. It's possible we're getting extremely unlucky and mLocationObject dies between invoking isOnConnected() and getLastLocation(), however that seems improbable to me. I suppose I can start to log before, between, and after the calls and find out.
LocationClient mLocationClient; // populated somewhere
public Location getLastLocation() {
if (!mLocationClient.isConnected()) {
return null;
}
Location location = null;
try {
location = mLocationClient.getLastLocation();
} catch (Exception e) {
if (!handleDeadObjectException(e)) {
throw e;
}
}
return location;
}
// logs, attempts to handle depending on user configuration
private boolean handleDeadObjectException(Exception e);