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 изменит имя службы, чтобы создать уникальный экземпляр. Мои вопросы:
- Какое ожидаемое время ожидания для рекламируемых услуг, если они больше не существуют?
- Есть ли способ обеспечить мой
onDestroy
вызывается, когда я запускаю новый экземпляр моего приложения? Будет ли это обстоятельство похоже на то, что может испытать пользователь, если он установит обновление моего приложения? то естьonDestroy
гарантированно вызывается, когда работающее приложение закрывается, чтобы можно было установить новую версию этого приложения? - Есть ли в моем приложении способ обнаружить старые регистрации и удалить их?
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, посмотрев источник здесь.
Подводя итог, я отвечу на вопросы из приглашения:
- Для 4.x тайм-аута нет, он будет работать до перезагрузки. Для 5.x NsdService отключает службу NSD, когда ваше приложение отключается.
- Нет способа гарантировать, что вызывается onDestroy(), более глубокое объяснение здесь. Установка через Android Studio убивает запущенное приложение без его вызова. Было бы интересно узнать, ведут ли себя обновления через App Store таким же образом или более корректно завершают работу запущенного приложения.
- Не проблема в 5.x, так как он убивает их сразу. В 4.x нет возможности удалить старые регистрации, так как вы сразу теряете слушателя регистрации.
Что касается пунктов 2) и 3), вы можете сделать следующее:
- К вашим услугам
onCreate()
метод, сгенерировать случайное число или метку времени и сохранить его в локальном поле; это будет идентификатор сервиса - Зарегистрировать пользовательский
BroadcastReceiver
в вашемService
, он будет реагировать на ваши действия - На каждом
Service
создание, отправьте трансляцию с вашим собственным действием и вашим текущимService
ID как дополнительный параметр - Для каждого активного
Service
зарегистрированныйBroadcastReceiver
будет срабатывать; Теперь сравните полученный идентификатор с идентификатором текущего сервиса- если они отличаются, вызовите
stopSelf()
- если они отличаются, вызовите
Таким образом, только последний Service
останется в живых.