问题
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:
- NSD Device Lost Message Not Received on Disabling Wifi
- 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