3

Android には、GMS (Google Mobile Services) から LocationClient オブジェクトをラップするクラスがあります。(LocationClient は com.google.android.gms.common.GooglePlayServicesClient を実装することに注意してください)。

残念ながら、LocationClient オブジェクトには DeadObjectExceptions をスローする癖があります (たとえば、locationClient.getLastLocation()を呼び出したとき)。これは、いくつかのログ メカニズムを通じて検出されます。ただし、奇妙なのは、LocationClient が DeadObjectExceptions をスローするように文書化されていないことです。この問題の再現性はなく、個人的に見たことはありませんが、多数のユーザーで発生しています。

その他の注意事項:

[a] 「Caused by: java.lang.IllegalStateException: android.os.DeadObjectException」という行は何ですか? これらの 2 つの例外タイプには、祖先と子孫の関係がありません

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

1 に答える 1

9

ドキュメントからDeadObjectException

ホスティング プロセスが存在しないため、呼び出しているオブジェクトは終了しました。

つまり、もう利用できない別のプロセスでオブジェクトに到達しようとしています。たとえば、別のプロセス (Google モバイル サービスなど) で実行されるサービスにバインドする場合、使用するIBinderは、リモート プロセス内のオブジェクトを「表す」ローカル オブジェクトです。リモート オブジェクトが使用できなくなったときに、ローカルの IBinder オブジェクトを使用しようとすると、DeadObjectExceptionが発生します。

そう...

a] 「Caused by: java.lang.IllegalStateException: android.os.DeadObjectException」という行は何ですか? これらの 2 つの例外タイプには、祖先と子孫の関係がありません

2 つの例外は、まったく関連していません。IllegalStateExceptionは実際の例外であり、DeadObjectExceptionルート例外です。

gms.location.LocationClient.getLastLocation()は、内部実装を公開する throw 要素を宣言したくないため (バインダーなどと連携して)、単純に宣言しません。ただし、 DeadObjectExceptionなどの例外が発生した場合でもスローする必要があるため、ランタイム例外IllegalStateException (スロー宣言を必要としない) を使用します。

[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
    }
}
于 2014-07-06T09:22:09.817 に答える