Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Network Service Discovery "timeout"?

Tags:

I'm using Network Service Discover (NSD) on Android to advertise a REST server on the device. My REST server is wrapped in an instance of android.app.Service.

In the onCreate, I successfully start the REST server and register my NSD service. I can see the NSD service name on other devices within my network (e.g. My Service).

In my onDestroy, I stop the REST Server and unregister the NSD service.

However, it seems that while developing, when I push a new instance of my app (via Eclipse), there's no guarantee that the service's onDestroy will be called. This means that My Service is still advertised, and the next time the service starts, I end up with My Service (1), My Service (2), etc.

I understand that NSD will amend the service name to create a unique instance. My questions are:

  1. What's the expected timeout for advertised services to be removed if they no longer exist?
  2. Is there a way to ensure my onDestroy is being called when I push a new instance of my app? Would this circumstance be similar to what a user might experience if they install an update of my app? i.e. is the onDestroy guaranteed to be called when a running app is shutdown so a new version of that app can be installed?
  3. Is there a way within my app to detect the old registrations and remove them?
like image 755
Kerry Avatar asked Mar 23 '14 03:03

Kerry


1 Answers

First of all, there is an open issue tracking this problem on the AOSP issue tracker. The person who filed the bug could repro in all Android 4.x versions but did not test with 5.x.

A brief explanation of terms:

  • NsdManager - the class that Android applications interface with to register their NSD service and discover other NSD services. NsdManager is really just a shell that establishes an asynchronous connection with NsdService.
  • NsdService(com.android.server.NsdService) - hidden Android system service that can have connections from multiple clients. Does all the heavy lifting and book-keeping for creating and managing NSD service and communicating events back to client applications.
  • NSD service - the service that NsdService creates on your behalf that advertises your app's presence over the network.

I just tested this issue with 5.1 and the issue is fixed(from the source it looks like the fix went into 5.0). I created a simple application that just registers an NsdService and logs when anything of note happens, including lifecycle events onCreate, onResume, onPause, and onDestroy. I got the following logs by rebooting, starting my application, and then reinstalling via 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

You can see that neither onPause() nor onDestroy() were called and thus my application did no explicit cleanup for the NSD service. NsdService is detecting when the AsyncChannel to the client is terminated and is cleaning it up properly. You can get a deeper understanding of the NsdService logs by looking at the source here.

Summing it all up, I'll respond to the questions from the prompt:

  1. For 4.x there is no timeout, it will stay up until reboot. For 5.x NsdService shuts down the NSD service when your app disconnects.
  2. There is no way to guarantee onDestroy() is called, a deeper explanation here. Installation via Android Studio killing the running application without it being called. Would be interesting to see if updates via the App Store behave the same way or more gracefully shut down the running app.
  3. Not a problem in 5.x since it kills them right away. In 4.x, there's no way to remove old registrations since you immediately lose the registration listener.
like image 158
Trevor Carothers Avatar answered Sep 19 '22 00:09

Trevor Carothers