在android上,我们有一个类,它包装gms(google mobile services)中的locationclient对象。(注意locationclient实现com.google.android.gms.common.googleplayservicesclient)。
不幸的是,locationclient对象有抛出deadobjectexception的习惯(例如,当我们调用locationclient.getlastlocation()时),我们通过几个日志机制检测到这些异常。然而,奇怪的是,locationclient没有被记录为抛出deadobjectexceptions,而且我只能捕获所说的deadobjectexceptions,它们发生的时间是0的1/40。我们对这个问题没有任何指责,我个人也从未见过,但它发生在我们的大量用户身上。
其他注释:
[A]关于“起因:java.lang.IllegalStateException:android.os.DeadobjectException”这一行是什么?这两种异常类型没有祖先-后代关系
[B]我在Android论坛上发帖,但他们当然以“错误论坛”拒绝了我的帖子,而且没有GMS论坛,所以我完全失去了运气。
总之,问题是:gms触发了这个奇怪的不可修补异常,那么这是怎么回事,我能做什么呢?
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)
—————————————————————————————————————————————————
这是我们的实际代码。您会注意到我们总是事先检查mlocationclient.isconnected()是否正确,所以这不是问题所在。有可能我们非常不走运,mlocationobject在调用isonconnected()和getlastlocation()之间死掉,但这对我来说似乎不太可能。我想我可以开始在通话前、通话间和通话后进行记录并找出答案。
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);
最佳答案
从文档中:
您正在调用的对象已死亡,因为其宿主进程不再存在。
意思是,你试图在一个不再可用的不同过程中到达一个对象。例如,如果绑定到在不同进程(即google mobile services)中运行的服务,则使用的DeadObjectException是一个本地对象,它“表示”远程进程中的一个对象。当远程对象不再可用,并且您正在尝试使用本地ibinder对象时,将得到deadobjectexception。
所以…
a]关于“起因:java.lang.IllegalStateException:android.os.DeadobjectException”这行是什么?这两种异常类型没有祖先-后代关系
这两个例外在任何方面都没有联系。IllegalStateException是实际的异常,DeadobjectException是根异常。
因为gms.location.locationclient.getLastLocation()不想声明公开内部实现的throw元素(使用绑定等),所以它根本不想声明。但是当发生deadobjectException之类的异常时,它仍然想抛出,因此它使用了运行时异常illegAlStateException(不需要throw声明)。
[B]我在Android论坛上发帖,但他们当然以“错误论坛”拒绝了我的帖子,而且没有GMS论坛,所以我完全失去了运气。
:(
总之,问题是:gms触发了这个奇怪的不可修补异常,那么这是怎么回事,我能做什么呢?
在使用gms locationclient时,需要在与客户端交互之前检查locationclient.isconnected()是否正确。注意,有时locationclient.isconnected()将返回true,但在调用locationclient.getLastLocation()之后,仍可能抛出java.lang.IllegalStateException:android.os.DeadobjectException,原因是线程问题和客户端连接时的竞争条件。当你检查的时候发现了,但是在你实际行动之前连接就断了。
您应该做的是a)检查客户端是否连接
if ( mLocationClient != null && mLocationClient.isConnected() ) {
mLocationClient.getLastLocation();
}
b)捕获IllegalStateException(而不是DeadobjectException)
if ( mLocationClient != null && mLocationClient.isConnected() ) {
try {
mLocationClient.getLastLocation();
} catch (IllegalStateException ex) {
// This will catch the exception, handle as needed
}
}