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

一笑奈何 提交于 2019-12-30 08:49:07

问题


My app is essentially a background service that needs to occasionally register an NSD service (Bonjour service) for the purpose of enabling discovery of a socket server run by the main background service (aka run by the app).

If I am reading the Android Bonjour Service doc correctly, this is how you start the Bonjour service (abbreviated for conciseness):

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

...and this is how you stop it:

mNsdManager.unregisterService(mRegistrationListener);

Here the part I can't wrap my head around: if the main service goes down abruptly, any Bonjour service that was registered at the time of the crash keeps running even though it no longer has a purpose (the socket server it helps discover is no longer around).

I can't event cleanup the zombie Bonjour services when the main service is restarted because the mRegistrationListener the service was initially registered with is also no longer around.

I suspect I am taking the wrong approach: how do I make sure I don't leave a mess of zombie Bonjour services behind after the main service crashed?


回答1:


Non-specific to Android Bonjour, you could try to handle the crash by setting up your service as is outlined in the answer here: Can I call a method before my application go to crash

If you can't set this up to make the unregisterService call, you should be able to set it up to use ActivityManager's API killBackgroundProcesses. This requires adding the permission to your manifest:

android.permission.KILL_BACKGROUND_PROCESSES



回答2:


If I understood you correctly the main service (the one with the server socket) registers/unregisters a Nsd service while a background service starts/stops discovery the Nsd service. I think this is what you do, so your "approach" is correct.

Regarding the problem, I should welcome you to Android Nsd. There are a lot of bugs with the framework (among which you can find your issue) that as of Android 6.0 haven't been fixed yet making developers use other frameworks instead.

Getting back to the issue, you might try UncaughtExceptionHandler, just keep in mind that all the callbacks are invoked by the system asynchronously, and you may get NPE when it calls mRegistrationListener.onServiceUnregistered(), because, as you said, "it is no longer around".

As to the service cleanup, theoretically it is possible, but only after NsdManager source code customization (access modifier of a few methods needs to be changed in order to reach and then unregister mRegistrationListener from another process that would lead to deleting it from a listener map of NsdManager). But it doesn't make any sense if the app is to be published on market.

There is another workaround you might try/experiment with. If I remember correctly (may be mistaken), the necessary cleanup takes place upon disabling Nsd. I tried it via adb:

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

However note, that making these calls programmatically may not be trivial and most likely require root, which, again, restricts the audience of your app.

Regarding the killBackgroundProcesses() method proposed by @thril, it takes a string with app's package name as parameter. But servicediscovery isn't an app, it's a system service. Also, you could try to kill the process (although I don't know which one) at runtime, but be careful, you should investigate what effect it brings to the system and be sure that the service will be started again when required (automatically by system or manually). Again, to do this root is needed.

Summing up the answer, before you proceed with Nsd, I highly recommend to do a search regarding its functionality/bugs in order to avoid possible wasting of your time and efforts. Some references in addition to the link provided above:

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

P.S. Personally I, after struggling with multiple Nsd framework bugs, ended up writing my own framework.



来源:https://stackoverflow.com/questions/34274029/android-stopping-a-bonjour-service-left-running-after-the-parent-process-quit

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!