Подтвердить что ты не робот

Android Network Service Discovery "тайм-аут"?

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

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

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

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

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

  • Какой ожидаемый тайм-аут для рекламируемых сервисов будет удален, если они больше не существуют?
  • Есть ли способ, чтобы мой onDestroy вызывался при нажатии нового экземпляра моего приложения? Может ли это обстоятельство быть похоже на то, что может возникнуть у пользователя, если они установят обновление моего приложения? то есть onDestroy гарантируется, что вызывается, когда запущенное приложение отключается, поэтому можно установить новую версию этого приложения?
  • Есть ли способ в моем приложении обнаружить старые регистрации и удалить их?
4b9b3361

Ответ 1

Прежде всего, существует проблема открыть проблему, отслеживающую эту проблему в трекере проблемы 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: [email protected]
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: [email protected]
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, посмотрев исходный здесь.

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

  • Для 4.x нет таймаута, он будет оставаться включенным до перезагрузки. Для 5.x NsdService отключает службу NSD, когда ваше приложение отключается.
  • Невозможно гарантировать, что onDestroy() вызывается, более глубокое объяснение здесь. Установка через Android Studio убивает запущенное приложение без его вызова. Было бы интересно посмотреть, будут ли обновления через App Store вести себя одинаково или более изящно закрывать запущенное приложение.
  • Не проблема в 5.x, так как она убивает их сразу. В 4.x нет способа удалить старые регистрации, так как вы сразу же потеряете регистрационный регистратор.

Ответ 2

Что касается пунктов 2) и 3), вы можете сделать следующее:

  • В вашем сервисе onCreate() создайте случайное число или временную метку и сохраните ее в локальном поле; это будет идентификатор службы
  • Зарегистрируйте пользовательский BroadcastReceiver в Service, он будет реагировать на ваши пользовательские действия
  • При каждом создании Service отправьте широковещательную рассылку с вашим пользовательским ACTION и вашим текущим идентификатором Service в качестве дополнительного параметра
  • Для каждого активного Service будет зарегистрирован зарегистрированный BroadcastReceiver; теперь сравните полученный идентификатор с текущим идентификатором службы
    • если они отличаются, вызовите stopSelf()

Таким образом, останется только последний Service.