Тайм-аут обнаружения сетевой службы Android?

Я использую Network Service Discover (NSD) на Android для объявления сервера REST на устройстве. Мой сервер REST заключен в экземпляр android.app.Service.

В onCreate я успешно запускаю сервер REST и регистрирую свою службу NSD. Я вижу имя службы NSD на других устройствах в моей сети (например, Моя служба).

В моем onDestroy я останавливаю сервер REST и отменяю регистрацию службы NSD.

Однако кажется, что во время разработки, когда я отправляю новый экземпляр своего приложения (через Eclipse), нет гарантии, что будет вызвана служба onDestroy. Это означает, что Моя служба по-прежнему рекламируется, и при следующем запуске службы я получаю сообщение Моя служба (1). , Моя служба (2) и т. д.

Я понимаю, что NSD изменит имя службы, чтобы создать уникальный экземпляр. Мои вопросы:

  1. Каково ожидаемое время ожидания для удаления рекламируемых услуг, если они больше не существуют?
  2. Есть ли способ убедиться, что мой onDestroy вызывается, когда я нажимаю новый экземпляр своего приложения? Будет ли это обстоятельство похоже на то, что может испытать пользователь, если установит обновление моего приложения? то есть гарантированно ли вызов onDestroy при завершении работы работающего приложения, чтобы можно было установить новую версию этого приложения?
  3. Есть ли способ в моем приложении обнаружить старые регистрации и удалить их?

person Kerry    schedule 23.03.2014    source источник
comment
Если вы хотите убедиться, что вызывается onDestroy, попробуйте использовать метод stopService.   -  person Philip Liberato    schedule 23.03.2014
comment
@Philip Мой текущий обходной путь — иметь кнопку, которую я могу нажать, чтобы остановить службу перед повторной установкой приложения. Однако, если я смогу получить ответы на вопросы 1 и 3, мне станет легче, когда я выпущу приложение :). В этом отношении вопрос 2 (отправка нового экземпляра приложения) актуален/похож на отправку обновления через Google Play? то есть есть ли шанс, что служба onDestroy не будет вызываться, если/когда пользователь обновит версию?   -  person Kerry    schedule 23.03.2014
comment
Хм, кажется, вопросы 1 и 3 не были бы проблемами, если бы вы выполнили условие для вопроса 2.   -  person Philip Liberato    schedule 23.03.2014
comment
Я столкнулся с той же проблемой. Вы нашли способ сделать это?   -  person Anil Maddala    schedule 10.10.2014
comment
OnDestory может вызываться, а может и не вызываться, гарантировать это невозможно. Вы можете попробовать повозиться с крючком выключения. Однако это также не гарантируется на 100%: developer.android.com/reference/java /lang/Время выполнения.html   -  person JohanShogun    schedule 06.08.2015
comment
Перехватчики завершения работы во время выполнения не запускаются в Android. Я тестировал onDestroy, и он работает примерно в 30% случаев. Моя другая идея состояла в том, чтобы иметь уведомление, которое говорит пользователю остановить службу и запустить службу в фоновом режиме, даже если действие закрыто.   -  person Dave Chen    schedule 06.08.2015


Ответы (2)


Прежде всего, это открыть отслеживание этой проблемы в системе отслеживания проблем AOSP. Человек, сообщивший об ошибке, мог воспроизвести ее во всех версиях Android 4.x, но не проверял ее на 5.x.

Краткое объяснение терминов:

  • NsdManager — класс, с которым приложения Android взаимодействуют для регистрации своей службы NSD и обнаружения других служб NSD. NsdManager — это просто оболочка, которая устанавливает асинхронное соединение с NsdService.
  • NsdService(com.android.server.NsdService) — скрытая системная служба Android, к которой могут подключаться несколько клиентов. Выполняет всю тяжелую работу и учет для создания службы NSD и управления ею, а также для передачи событий клиентским приложениям.
  • Служба NSD – служба, которую NsdService создает от вашего имени и которая сообщает о присутствии вашего приложения в сети.

Я только что проверил эту проблему с 5.1, и проблема исправлена ​​(из источника похоже, что исправление вошло в 5.0). Я создал простое приложение, которое просто регистрирует NsdService и регистрирует все важные события, включая события жизненного цикла onCreate, onResume, onPause и onDestroy. Я получил следующие журналы, перезагрузившись, запустив свое приложение, а затем переустановив его через Android Studio.

W/SimpleNsdActivity(14379): onCreate
D/NsdService( 3516): startMDnsDaemon
D/NsdService( 3516): New client listening to asynchronous messages
D/NsdService( 3516): New client, channel: com.android.internal.util.AsyncChannel
@3c114a11 messenger: android.os.Messenger@3213e776
D/NsdService( 3516): Register service
D/NsdService( 3516): registerService: 2 name: NsdTest, type: _http._tcp., host:
null, port: 1349
W/SimpleNsdActivity(14379): onResume
D/NsdService( 3516): Register 1 2
W/SimpleNsdActivity(14379): onServiceRegistered as NsdTest
D/NsdService( 3516): SERVICE_REGISTERED Raw: 606 2 "NsdTest"
D/NsdService( 3516): Client disconnected
D/NsdService( 3516): Terminating client-ID 1 global-ID 2 type 393225
D/NsdService( 3516): unregisterService: 2
D/NsdService( 3516): stopMDnsDaemon
W/SimpleNsdActivity(15729): onCreate
D/NsdService( 3516): startMDnsDaemon
D/NsdService( 3516): New client listening to asynchronous messages
D/NsdService( 3516): New client, channel: com.android.internal.util.AsyncChannel
@38bace07 messenger: android.os.Messenger@26d8cd5d
D/NsdService( 3516): Register service
D/NsdService( 3516): registerService: 3 name: NsdTest, type: _http._tcp., host:
null, port: 1349
D/NsdService( 3516): Register 1 3
W/SimpleNsdActivity(15729): onResume
D/NsdService( 3516): SERVICE_REGISTERED Raw: 606 3 "NsdTest"
W/SimpleNsdActivity(15729): onServiceRegistered as NsdTest

Вы можете видеть, что ни onPause(), ни onDestroy() не вызывались, и поэтому мое приложение не выполняло явную очистку для службы NSD. NsdService обнаруживает, когда AsyncChannel для клиента завершается, и очищает его должным образом. Вы можете получить более глубокое представление о журналах NsdService, просмотрев источник здесь.

Подводя итог, отвечу на вопросы из подсказки:

  1. Для 4.x таймаута нет, он будет работать до перезагрузки. Для 5.x NsdService отключает службу NSD, когда ваше приложение отключается.
  2. Невозможно гарантировать вызов onDestroy(), более подробное объяснение здесь. Установка через Android Studio убивает работающее приложение без его вызова. Было бы интересно посмотреть, будут ли обновления через App Store вести себя так же или более изящно закрывать работающее приложение.
  3. Не проблема в 5.x, так как он их сразу убивает. В 4.x нет возможности удалить старые регистрации, так как вы немедленно теряете прослушиватель регистрации.
person Trevor Carothers    schedule 11.08.2015
comment
Именно то, что я искал. Мне было интересно, почему мне пришлось перезагрузить устройство, чтобы NSD заработал (в моем тестировании). Я рад, что 5.x решает эту проблему, но очень жаль, что на самом деле нечего делать, кроме как использовать onPause/onResume (в крайнем случае). - person Dave Chen; 11.08.2015

По пунктам 2) и 3) можно сделать следующее:

  • В методе onCreate() вашей службы сгенерируйте случайное число или отметку времени и сохраните ее в локальном поле; это будет ID службы
  • Зарегистрируйте пользовательское BroadcastReceiver в своем Service, оно будет реагировать на ваше пользовательское ДЕЙСТВИЕ.
  • При каждом создании Service отправьте широковещательную рассылку с вашим пользовательским ACTION и вашим текущим Service ID в качестве дополнительного параметра.
  • For each active Service, the registered BroadcastReceiver will be triggered; now compare the received ID with the current service's ID
    • if they differ, invoke stopSelf()

Таким образом, в живых останутся только последние Service.

person bonnyz    schedule 07.08.2015
comment
Вы не можете отменить регистрацию службы после завершения действия, потому что вам нужен прослушиватель службы. Я думаю, вы могли бы установить идентификатор службы на отметку времени, а затем подключиться к службе с самым большим идентификатором. - person Dave Chen; 08.08.2015
comment
@DaveChen Служба может остановить себя, когда захочет (в данном случае, когда она получает трансляцию). Деятельность не имеет значения. - person bonnyz; 10.08.2015
comment
@DaveChen Я думаю, что есть путаница из-за либерального использования термина «Сервис» в подсказке. Насколько я понимаю, служба Android всегда отключается при обновлении приложения, но ее метод onDestroy() не всегда вызывается. Это приводит к утечке службы NSD. - person Trevor Carothers; 11.08.2015