Android Network Service Discovery "время ожидания"?

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

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

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

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

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

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

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 нет возможности удалить старые регистрации, так как вы сразу теряете слушателя регистрации.

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

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

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

Другие вопросы по тегам