studio example android android-nsd

example - android wifi p2p



¿Descubrimiento del servicio de red de Android “timeout”? (2)

Estoy usando Network Service Discover (NSD) en Android para anunciar un servidor REST en el dispositivo. Mi servidor REST está envuelto en una instancia de android.app.Service .

En el onCreate , inicio con éxito el servidor REST y registro mi servicio NSD. Puedo ver el nombre del servicio NSD en otros dispositivos dentro de mi red (por ejemplo, Mi servicio ).

En mi onDestroy , detengo el servidor REST y anulo el registro del servicio NSD.

Sin embargo, parece que al desarrollar, cuando presiona una nueva instancia de mi aplicación (a través de Eclipse), no hay garantía de que se onDestroy al servicio onDestroy del servicio. Esto significa que Mi servicio todavía se anuncia, y la próxima vez que comience el servicio, termino con Mi servicio (1) , Mi servicio (2) , etc.

Entiendo que NSD modificará el nombre del servicio para crear una instancia única. Mis preguntas son:

  1. ¿Cuál es el tiempo de espera esperado para que se eliminen los servicios anunciados si ya no existen?
  2. ¿Hay alguna manera de garantizar que se onDestroy cuando presione una nueva instancia de mi aplicación? ¿Esta circunstancia sería similar a la que podría experimentar un usuario si instala una actualización de mi aplicación? es decir, ¿se garantiza que se llamará a onDestroy cuando una aplicación en ejecución se apaga para poder instalar una nueva versión de esa aplicación?
  3. ¿Hay alguna forma dentro de mi aplicación para detectar los registros anteriores y eliminarlos?

Con respecto a los puntos 2) y 3), puede hacer lo siguiente:

  • En el método onCreate() su servicio, genere un número aleatorio o una marca de tiempo y guárdelo en un campo local; este será el ID de servicio
  • Registre un BroadcastReceiver personalizado en su Service , reaccionará a su ACCIÓN personalizada.
  • En cada creación del Service , envíe una transmisión con su ACCIÓN personalizada y su ID de Service actual como parámetro adicional
  • Para cada Service activo, se activará el BroadcastReceiver registrado; Ahora compare la ID recibida con la ID del servicio actual
    • si difieren, invoca stopSelf()

De esta manera, solo el último Service permanecerá vivo.


En primer lugar, hay un problema abierto que sigue este problema en el rastreador de problemas de AOSP. La persona que presentó el error pudo reproducir en todas las versiones de Android 4.x pero no probó con 5.x.

Una breve explicación de los términos:

  • NsdManager : la clase con la que las aplicaciones de Android interactúan para registrar su servicio NSD y descubrir otros servicios NSD. NsdManager es en realidad solo un shell que establece una conexión asíncrona con NsdService.
  • NsdService (com.android.server.NsdService): servicio oculto del sistema de Android que puede tener conexiones de varios clientes. Hace todo el trabajo pesado y la contabilidad para crear y administrar el servicio de NSD y comunicar eventos a las aplicaciones cliente.
  • Servicio NSD : el servicio que NsdService crea en su nombre y que anuncia la presencia de su aplicación en la red.

Acabo de probar este problema con 5.1 y el problema está solucionado (desde el origen parece que la solución se fue a 5.0). Creé una aplicación simple que solo registra un NsdService y registra cuando ocurre algo importante, incluidos los eventos del ciclo de vida enCreate, onResume, onPause y onDestroy. Obtuve los siguientes registros al reiniciar, iniciar mi aplicación y luego volver a instalar a través de 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

Puede ver que no se onPause() ni a onDestroy() y, por lo tanto, mi aplicación no realizó una limpieza explícita para el servicio NSD. NsdService está detectando cuando el AsyncChannel al cliente finaliza y lo está limpiando correctamente. Puede obtener una comprensión más profunda de los registros de NsdService consultando la fuente here .

Resumiendo todo, responderé a las preguntas del mensaje:

  1. Para 4.x no hay tiempo de espera, permanecerá activo hasta que se reinicie. Para 5.x, NsdService cierra el servicio NSD cuando la aplicación se desconecta.
  2. No hay forma de garantizar que se llame aDestroy (), una explicación más detallada here . Instalación a través de Android Studio matando a la aplicación en ejecución sin que sea llamada. Sería interesante ver si las actualizaciones a través de la App Store se comportan de la misma manera o, de manera más elegante, apague la aplicación en ejecución.
  3. No hay problema en 5.x, ya que los mata de inmediato. En 4.x, no hay forma de eliminar los registros antiguos, ya que pierde de inmediato la escucha del registro.