#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.