GMS :: LocationClient(Android)中的DeadObjectException

时间:2014-06-18 14:50:11

标签: android location-client

在Android上,我们有一个包装来自GMS(Google移动服务)的LocationClient对象的类。 (请注意,LocationClient实现了com.google.android.gms.common.GooglePlayServicesClient)。

不幸的是,LocationClient对象习惯于抛出DeadObjectExceptions(例如,当我们调用 locationClient.getLastLocation() 时),我们通过几种日志记录机制检测到它。然而,奇怪的是,LocationClient没有被记录为抛出DeadObjectExceptions,而且我只能捕获所述DeadObjectExceptions~1 / 40发生的时间o_0。我们对此问题没有任何责任,而且我个人从未见过它,但是对于我们的大量用户来说却是如此。

其他说明:

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

------------ ADDENDUM ------------- 这是我们的实际代码。您会注意到我们总是事先检查是否有mLocationClient.isConnected(),因此不是问题。我们可能会非常不走运,而且在调用isOnConnected()和getLastLocation()之间,mLocationObject会死掉,但这对我来说似乎不太可能。我想我可以在呼叫之前,之间和之后开始记录并查找。

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

1 个答案:

答案 0 :(得分:9)

来自文档DeadObjectException

  

您呼叫的对象已经死亡,因为其托管过程已不复存在。

意思是,您正尝试在不再可用的其他进程中访问对象。例如,如果您绑定到在不同进程(即Google移动服务)中运行的服务,则您使用的IBinder是一个“代表”远程进程中的对象的本地对象。当远程对象不再可用,并且您尝试使用本地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
    }
}