Исключение DeadObjectException в GMS ::LocationClient (Android)

#android #location-client

#Android #местоположение-клиент

Вопрос:

На Android у нас есть класс, который переносит объект LocationClient из GMS (мобильные сервисы Google). (Обратите внимание, что LocationClient реализует com.google.android.gms.common.GooglePlayServicesClient).

К сожалению, объект LocationClient имеет привычку вызывать исключения DeadObjectException (например, когда мы вызываем 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)
  

———— ДОПОЛНЕНИЕ ————-
Вот наш фактический код. Вы заметите, что мы всегда проверяем, является ли 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);
  

Комментарии:

1. Итак, вы выяснили, как вы справились с проблемой??

2. Привет, у меня такая же проблема. Вы нашли решение

3. @MrMike нет. Я ушел из этой компании и кратко ознакомился с этим в другой компании, но проблема, по-видимому, исчезла для нас к середине 2015 года. С тех пор я избегал геокода.

4. Спасибо за ваш ответ

Ответ №1:

Из документации 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 и причиной этого являются проблемы с потоками и условия гонки, когда клиент был подключен при проверке, но затем соединение было потеряно до вашего фактического действия.

Что вам следует сделать, так это а) Проверить, подключен ли клиент

 if ( mLocationClient != null amp;amp; mLocationClient.isConnected() ) {   
    mLocationClient.getLastLocation();
}
  

б) Перехватить исключение IllegalStateException (а не исключение DeadObjectException)

 if ( mLocationClient != null amp;amp; mLocationClient.isConnected() ) {   
    try {
        mLocationClient.getLastLocation();
    } catch (IllegalStateException ex) {
        // This will catch the exception, handle as needed
    }
}
  

Комментарии:

1. Я прокомментировал как дополнение к исходному сообщению (для записи здесь потребовалось слишком много места). Также обратите внимание, что handleDeadObjectException (исключение e) обрабатывает все типы исключений, и там всегда была явная логика для регистрации и осторожной обработки как IllegalStateExceptions, так и DeadObjectExceptions, так что это должно касаться вашего пункта (b). Мы начинаем думать, что нам нужно создавать / уничтожать объекты LocationClient в разумных пределах — не сохраняя их слишком долго, не удаляя их слишком быстро, когда пользователь переключается между действиями. Переключение на связанную службу может помочь нам в этом.

2. Во-первых, перехват исключения — это то, что вы должны уметь делать в любом случае. Таким образом, из-за этого не должно быть никаких проблем с фактическим сбоем. Во-вторых, вы создаете несколько клиентов местоположения? может быть, вы могли бы попробовать управлять только одним LocationClient…

3. Правильно, то, что я не могу поймать исключение, — это то, что совершенно нереально в этом. Нет, мы создаем один LocationClient как одноэлементный и сохраняем его навсегда, но я думаю, что GMS каким-то образом позволяет ему / чему-то внутренне перерабатываться, отсюда и DOE. Мысль переходит к случаю, когда мы по-прежнему создаем только один location client в любой момент времени, но мы обязательно отключаем его время от времени.

4. Для меня это не похоже на пуленепробиваемое решение — это может уменьшить проблему, но не исправит ее. Я бы начал с определения одного клиента местоположения и выяснения, в чем проблема с исключением. Не видя фактического кода, мне было бы очень сложно определить проблему. Должно сработать.

5. кроме того, мы поговорили с некоторыми представителями Google, и, вероятно , это было вызвано состоянием гонки внутри GooglePlayServices.