studio direct developer android android-lifecycle android-nsd

android - direct - NsdManager no detiene el descubrimiento de servicios



p2p connection android studio (2)

En la aplicación de Android que estoy desarrollando actualmente, quiero conectarme a redes de configuración cero utilizando NsdManager .

NsdManager ejecutar el descubrimiento del servicio de red y conectarme a la red deseada, pero después de detener el descubrimiento, el subproceso NsdManager todavía se está ejecutando. Esto conduce a la situación cuando, después de algunas rotaciones de pantalla, hay muchos subprocesos de NsdManager que están buscando una conexión.

Cuando cualquier red está disponible, el dispositivo intenta sincronizarse muchas veces, por lo que cada NsdManager todavía está activo, a pesar de detener el descubrimiento del servicio.

Bellow es mi código:

package dtokarzewsk.nsdservicetest; import android.content.Context; import android.net.nsd.NsdManager; import android.net.nsd.NsdServiceInfo; import android.util.Log; import java.net.InetAddress; public class NsdTest { private static final String NSD_SERVICE_NAME = "TestService"; private static final String NSD_SERVICE_TYPE = "_http._tcp."; private int mPort; private InetAddress mHost; private Context mContext; private NsdManager mNsdManager; private android.net.nsd.NsdManager.DiscoveryListener mDiscoveryListener; private android.net.nsd.NsdManager.ResolveListener mResolveListener; public NsdTest(Context context) { mContext = context; } public void startListening() { initializeResolveListener(); initializeDiscoveryListener(); mNsdManager = (NsdManager) mContext.getSystemService(Context.NSD_SERVICE); mNsdManager.discoverServices(NSD_SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener); } public void stopListening() { mNsdManager.stopServiceDiscovery(mDiscoveryListener); } private void initializeResolveListener() { mResolveListener = new NsdManager.ResolveListener() { @Override public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) { Log.d("NSDService test","Resolve failed"); } @Override public void onServiceResolved(NsdServiceInfo serviceInfo) { NsdServiceInfo info = serviceInfo; Log.d("NSDService test","Resolve failed"); mHost = info.getHost(); mPort = info.getPort(); Log.d("NSDService test","Service resolved :" + mHost + ":" + mPort); } }; } private void initializeDiscoveryListener() { mDiscoveryListener = new NsdManager.DiscoveryListener() { @Override public void onStartDiscoveryFailed(String serviceType, int errorCode) { Log.d("NSDService test","Discovery failed"); } @Override public void onStopDiscoveryFailed(String serviceType, int errorCode) { Log.d("NSDService test","Stopping discovery failed"); } @Override public void onDiscoveryStarted(String serviceType) { Log.d("NSDService test","Discovery started"); } @Override public void onDiscoveryStopped(String serviceType) { Log.d("NSDService test","Discovery stopped"); } @Override public void onServiceFound(NsdServiceInfo serviceInfo) { NsdServiceInfo info = serviceInfo; Log.d("NSDService test","Service found: " + info.getServiceName()); if (info.getServiceName().equals(NSD_SERVICE_NAME)) mNsdManager.resolveService(info, mResolveListener); } @Override public void onServiceLost(NsdServiceInfo serviceInfo) { NsdServiceInfo info = serviceInfo; Log.d("NSDService test","Service lost: " + info.getServiceName()); } }; } }

Y en la Activity principal:

private NsdTest mNsdTest; @Override protected void onResume() { super.onResume(); mNsdTest = new NsdTest(this); mNsdTest.startListening(); } @Override protected void onPause() { mNsdTest.stopListening(); super.onPause(); }

¿Como puedo solucionar este problema?


El motivo es porque NsdManager.stopServiceDiscovery es asíncrono. En la documentation , debe esperar a que onDiscoveryStopped(String) la sesión de descubrimiento.

El hecho de que se detenga inmediatamente después de enviar la solicitud asíncrona probablemente significa que la devolución de llamada que se habría activado se "perdió" debido a que su aplicación estaba en segundo plano. Las devoluciones de llamada asíncronas tienen el hábito de no manejar bien el fondo.


Mi solución actual para esto, es hacer que la clase que contiene NsdManager (NsdTest en el ejemplo anterior) sea un singleton con un contexto cambiante.

No cambia el hecho de que el subproceso de NSdManager se está ejecutando constantemente incluso después de detener el descubrimiento del servicio, pero al menos solo hay un subproceso de NsdManager activo después de reanudar la aplicación.

Tal vez no sea la forma más elegante, pero es suficiente para mí.

public class NsdTest { private static NsdTest mInstance; private static final String NSD_SERVICE_NAME = "TestService"; private static final String NSD_SERVICE_TYPE = "_http._tcp."; private int mPort; private InetAddress mHost; private Context mContext; private NsdManager mNsdManager; private android.net.nsd.NsdManager.DiscoveryListener mDiscoveryListener; private android.net.nsd.NsdManager.ResolveListener mResolveListener; private static NsdTest mInstance; private NsdTest(Context context) { mContext = context; } public static NsdTest getInstance(Context context) { if (mInstance == null) { mInstance = new NsdTest(context); } else { mContext = context; } return mInstance; } ...}

Si alguien sabe mejor solución, por favor publíquelo.