2015-12-14 4 views
5

Мое приложение - это, по существу, справочная служба, которая должна периодически регистрировать услугу NSD (Bonjour) с целью включения обнаружения сервера сокетов, выполняемого основным фоновое обслуживание (также выполняемое приложением).Android: остановка сервиса Bonjour оставлена ​​после завершения родительского процесса

Если я правильно читал Android Bonjour Service doc, это то, как вы начинаете Bonjour службы (сокращенную для краткости):

mNsdManager = Context.getSystemService(Context.NSD_SERVICE); 
mDiscoveryListener = new NsdManager.DiscoveryListener() 
mNsdManager.discoverServices(
     SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener); 

... и это, как вы остановить его:

mNsdManager.unregisterService(mRegistrationListener); 

Здесь часть, на которую я не могу окутать голову: если главная служба резко падает, любая служба Bonjour, которая была зарегистрирована во время сбоя, продолжает работать, даже если у нее больше нет цели (сервер сокетов помогает дискотеке ver больше не существует).

Невозможно провести мероприятия по очистке зомби Bonjour услуг, когда основная услуга перезапускается, потому что mRegistrationListener услуга изначально была зарегистрирована, также больше нет.

Я подозреваю, что принимаю неправильный подход: как я могу убедиться, что я не оставляю беспорядок службы зомби Bonjour после того, как основной сервис разбился?

ответ

1

Неспецифического для Android Bonjour, вы можете попробовать справиться с аварией по настройке службы, как указано в ответе здесь: Can I call a method before my application go to crash

Если вы не можете установить это сделать вызов unregisterService, вы должны установить его для использования API-интерфейса ActivityManager killBackgroundProcesses. Для этого нужно добавить разрешения на манифест:

android.permission.KILL_BACKGROUND_PROCESSES 
+0

Спасибо, что поймать неперехваченные исключения с помощью 'UncaughtExceptionHandler' - это, вероятно, путь - хотя я надеялся на способ запустить сервис Bonjour в основном процессе (я нахожу, что это удивительно, что реализация Android не позволяет этого варианта) , Я приму ваш ответ, если в ближайшие пару дней ничего не получится. – Hugo

+0

Согласен, вы бы подумали, что есть правильный способ справиться с этим. Я не мог найти документацию для поддержки теории, но она может быть обработана ОС. Возможно, Google думает, что люди могут не думать об этом вообще, поэтому они должны автоматически справиться с этим! –

+0

Спасибо @thril, используя 'UncaughtExceptionHandler', чтобы отменить регистрацию службы, которая работала для меня (я успешно протестировал, сбой службы через несколько секунд после регистрации службы, используя таймер демона, работающий в отдельном потоке) – Hugo

2

Если я правильно понял основную услугу (тот, с сокетом сервера) регистрирует/отменяет регистрацию Nsd службы в то время как фоновая служба запускает/останавливает открытие в Nsd обслуживании. Я думаю, что это то, что вы делаете, поэтому ваш «подход» правильный.

Что касается проблемы, я должен приветствовать вас на Android Nsd. Есть много bugs с каркасом (среди которых вы можете найти свою проблему), что с Android 6.0 еще не исправлены, но разработчики используют другие фреймворки.

Возвращаясь к вопросу, вы можете попробовать UncaughtExceptionHandler, просто имейте в виду, что все обратные вызовы вызываются системой асинхронно, и вы можете получить NPE, когда он вызывает mRegistrationListener.onServiceUnregistered(), потому что, как вы сказали, «это уже не вокруг ".

Как очистки службы, теоретически это возможно, но только после того, как NsdManager исходного кода настройка (модификатор доступа нескольких методов должна быть изменена для того, чтобы достичь, а затем незарегистрированного mRegistrationListener из другого процесса, который приведет к удалению его от карты слушателя NsdManager). Но это не имеет никакого смысла, если приложение должно быть опубликовано на рынке.

Существует еще одно обходное решение, с которым вы можете попробовать/поэкспериментировать. Если я правильно помню (может ошибаться), необходимая очистка происходит после отключения Nsd.Я попробовал его с помощью adb:

// Disable 
adb shell service call servicediscovery 2 
// Enable 
adb shell service call servicediscovery 2 i32 1 

Однако обратите внимание, что делает эти вызовы программно не может быть тривиальным и, скорее всего, потребуется корень, который, опять же, ограничивает аудиторию вашего приложения.

Относительно метода killBackgroundProcesses(), предложенного @thril, в качестве параметра требуется строка с именем пакета приложения. Но servicediscovery не приложение, это системный сервис. Кроме того, вы можете попытаться убить процесс (хотя я не знаю, какой из них) во время выполнения, но будьте осторожны, вам следует изучить, какой эффект он приносит системе, и быть уверенным, что служба будет возобновлена ​​по мере необходимости (автоматически по системе или вручную). Опять же, для этого нужен корень.

Подводя итог, прежде чем приступить к работе Nsd, я настоятельно рекомендую выполнить поиск относительно его функциональности/ошибок, чтобы избежать возможного траты времени и усилий. Некоторые ссылки в дополнение к ссылке приведенные выше:

  1. NSD Device Lost Message Not Received on Disabling Wifi
  2. NsdManager doesn't stop service discovery

P.S. Лично я, столкнувшись с несколькими ошибками фрейма Nsd, в итоге написал свою собственную фреймворк.

+0

Спасибо @Onik, в конце концов используя 'UncaughtExceptionHandler', работал как запроектированный, я успешно протестировал, сбой основной службы из отдельного потока, используя таймер демона (' Таймер таймера = новый таймер (true); timer.schedule (новый SimulateUncaughtException(), 2000);) – Hugo

+0

Очень хорошо @Hugo, обработка 'Nsd' работы в отдельном потоке - хорошая идея, - ясно, что у вас есть время, чтобы отменить регистрацию службы в этом случае. Хотя, я по-прежнему рекомендую проверить все обратные вызовы «Nsd», особенно при включении/отключении 'Wifi' (' Ethernet') ... – Onik

Смежные вопросы