Android : 在父进程突然退出后 运行 停止 Bonjour 服务

Android : Stopping a Bonjour service left running after the parent process quit abrubtly

我的应用程序本质上是一个后台服务,需要偶尔注册一个 NSD 服务(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 服务都会保持 运行ning,即使它不再有目的(它帮助发现的套接字服务器不再存在)。

我无法在主服务重新启动时清理僵尸 Bonjour 服务,因为最初注册的 mRegistrationListener 服务也不再存在。

我怀疑我采取了错误的方法:如何确保在主服务崩溃后我不会留下一堆僵尸 Bonjour 服务?

非特定于 Android Bonjour,您可以尝试按照此处答案中所述设置您的服务来处理崩溃:Can I call a method before my application go to crash

如果您无法将其设置为进行 unregisterService 调用,您应该能够将其设置为使用 ActivityManager 的 API killBackgroundProcesses。这需要将权限添加到您的清单:

android.permission.KILL_BACKGROUND_PROCESSES

如果我对你的理解正确的话,主要服务(带有服务器套接字的服务)registers/unregisters Nsd 服务,而后台服务 starts/stops 发现 Nsd 服务.我认为这就是你所做的,所以你的 "approach" 是正确的。

关于这个问题,欢迎大家AndroidNsd。截至 Android 6.0 为止,框架中有很多 bugs 问题(您可以在其中找到您的问题)尚未得到修复,这使得开发人员改用其他框架。

回到问题上来,你可以尝试UncaughtExceptionHandler,只要记住所有的回调都是由系统异步调用的,当它调用[=17时你可能会得到NPE =],因为正如你所说,"it is no longer around".

关于服务清理,理论上是可以的,但是需要NsdManager源代码定制后(需要更改一些方法的访问修饰符才能到达然后注销mRegistrationListener来自另一个进程,这将导致从 NsdManager 的侦听器映射中删除它)。但是如果要在市场上发布该应用程序没有任何意义。

您可以 try/experiment 使用另一种解决方法。如果我没记错的话(可能有误),必要的清理是在禁用 Nsd 时进行的。我通过 adb:

尝试过
// Disable
adb shell service call servicediscovery 2
// Enable
adb shell service call servicediscovery 2 i32 1

但是请注意,以编程方式进行这些调用可能并不简单,而且很可能需要 root,这再次限制了您的应用程序的受众。

关于@thril提出的killBackgroundProcesses()方法,它以应用程序包名的字符串作为参数。但是 servicediscovery 不是应用程序,它是系统服务。此外,您可以尝试在运行时终止该进程(虽然我不知道是哪个进程),但要小心,您应该调查它对系统带来的影响,并确保该服务将在需要时再次启动(自动通过系统或手动)。同样,要执行此操作需要 root。

总结一下答案,在您继续 Nsd 之前,我强烈建议您对其 functionality/bugs 进行搜索,以免浪费您的时间和精力。除了上面提供的 link 之外的一些参考资料:

  1. NSD Device Lost Message Not Received on Disabling Wifi

P.S。就我个人而言,在与多个 Nsd 框架错误作斗争之后,最终编写了我自己的框架。