2012-10-09 25 views
27

Próbuję uruchomić aplikację przy użyciu usługi Android Native Service Discovery, ale czasami po uruchomieniu aplikacji nie wykrywa wszystkich usług z mojej sieci. Używam kodu od https://github.com/joeluchoa/nsd za pomocą czterech nexusów galaktyk, a większość razy każdy z nich odkrywa różną liczbę usług w tym samym czasie.Android NSD nie odkrywa wszystkich usług

Zasadniczo biegnę usługę z ServerSocket:

ServerSocket server = new ServerSocket(0); 
Log.i(TAG, "IP " + server.getInetAddress() 
     + ", running on port " + server.getLocalPort()); 

Intent intent = new Intent(MySocket.this, 
     MyPresence.class); 
intent.putExtra("PORT", server.getLocalPort()); 
startService(intent); 

Potem publikuje je z wykorzystaniem metody RegisterService z NsdManager:

NsdServiceInfo serviceInfo = new NsdServiceInfo(); 

serviceInfo.setServiceName(Build.SERIAL + "-" + new Date().getTime()); 
serviceInfo.setServiceType(SERVICE_TYPE); 
serviceInfo.setPort(port); 

mNsdManager.registerService(serviceInfo, NsdManager.PROTOCOL_DNS_SD, 
     mRegistrationListener); 

Aby odkryć usługi używam discoverServices metodę z NsdManager:

mNsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, 
     mDiscoveryListener); 

Z mDiscoveryListener w następujący sposób:

mDiscoveryListener = new NsdManager.DiscoveryListener() { 

    @Override 
    public void onDiscoveryStarted(String regType) { 
     Log.d(TAG, "Service discovery started"); 
    } 

    @Override 
    public void onServiceFound(NsdServiceInfo service) { 
     Log.d(TAG, "Service discovery success"); 
     Log.d(TAG, String.format("%s %s %s %d", 
       service.getServiceName(), service.getServiceType(), 
       service.getHost(), service.getPort())); 
     if (!service.getServiceType().contains(SERVICE_TYPE)) { 
      Log.d(TAG, 
        "Unknown Service Type: " + service.getServiceType()); 
     } else if (service.getServiceName().equals(mServiceName)) { 
      Log.d(TAG, "Same machine: " + mServiceName); 
     } else { 
      mNsdManager.resolveService(service, mResolveListener); 
     } 
    } 

    @Override 
    public void onServiceLost(NsdServiceInfo service) { 
     Log.e(TAG, "service lost" + service); 
    } 

    @Override 
    public void onDiscoveryStopped(String serviceType) { 
     Log.i(TAG, serviceType + " Discovery stopped: " + serviceType); 
    } 

    @Override 
    public void onStartDiscoveryFailed(String serviceType, int errorCode) { 
     Log.e(TAG, serviceType + " Discovery failed: Error code:" 
       + errorCode); 
     mNsdManager.stopServiceDiscovery(this); 
    } 

    @Override 
    public void onStopDiscoveryFailed(String serviceType, int errorCode) { 
     Log.e(TAG, serviceType + " Discovery failed: Error code:" 
       + errorCode); 
     mNsdManager.stopServiceDiscovery(this); 
    } 
}; 

Czy robię coś nie tak? Czy ktoś zna rozwiązanie lub obejście tego problemu?

+0

I camer acros poście, starając się naprawić NPE, który wydaje się popup, kiedy mam dwóch urządzeń w sieci o tej samej informacji NSD ... Tak, I don” t masz dla ciebie jeszcze odpowiedź, ale zauważam, że próbujesz uzyskać informacje, których nie rozwiązałeś w swoim logu. –

+2

Powszechną praktyką dla wszystkich programistów jest śledzenie tego, że za pomocą polecenia try catch lub wypisz wszystkie zmienne, aby znaleźć błędy, –

+0

dopiero odkrywasz usługi SERVICE_TYPE, które w tym przykładzie są serwerami http. –

Odpowiedz

1

Miałem ten sam problem, ponownie pomógł. Spróbuj użyć :)

1

Obawiam się, że nadal występują błędy w implementacji, które powodują utratę usług. Zrobiłem kilka dni testów z wieloma urządzeniami z Androidem i MacBookiem, i to po prostu nie działa przez cały czas. Udokumentowałem moje wnioski na temat zgłoszenia błędu w systemie śledzenia błędów Androida: https://code.google.com/p/android/issues/detail?id=178080

1

Mam wrażenie, że cała implementacja NSD w systemie Android musi być nieco niestabilna. Mam również proste działanie, aby pokazać cykl życia (żadne gniazda nie są otwarte), a czasami działa, a czasami nie działa. Po prostu tego nie rozumiem. Oto aktywny jeśli ktoś ma jakiś wgląd:

https://github.com/mholzel/Dump/blob/master/NetworkServiceDiscoveryViaWifi.java

Z drugiej strony, NSD Wi-Fi Direct w oparciu wydaje się być bardzo wiarygodne dla mnie:

https://github.com/mholzel/Dump/blob/master/NetworkServiceDiscoveryViaWifiDirect.java

Należy pamiętać, że żaden z nich Działania mają dowolne zasoby, więc po prostu dodaj Działania do Manifestu z odpowiednimi uprawnieniami.

0

Może być trochę za późno na odpowiedź, ale znalazłem dobre rozwiązanie dla NSD dla Androida na swojej stronie programisty. Zrobiłem kilka modyfikacji i działa idealnie dobrze.

public class NsdClient { 
private Context mContext; 

private NsdManager mNsdManager; 
NsdManager.DiscoveryListener mDiscoveryListener; 

//To find all the available networks SERVICE_TYPE = "_services._dns-sd._udp" 
public static final String SERVICE_TYPE = "_hap._tcp."; 
public static final String TAG = "NsdClient"; 

private static ArrayList<NsdServiceInfo> ServicesAvailable = new ArrayList<>(); 

public NsdClient(Context context) { 
    mContext = context; 
    mNsdManager = (NsdManager) context.getSystemService(Context.NSD_SERVICE); 
} 

public void initializeNsd() { 
    initializeDiscoveryListener(); 
} 

public void initializeDiscoveryListener() { 
    mDiscoveryListener = new NsdManager.DiscoveryListener() { 

     @Override 
     public void onDiscoveryStarted(String regType) { 
      Log.d(TAG, "Service discovery started " + regType); 
     } 

     @Override 
     public void onServiceFound(NsdServiceInfo service) { 
      Log.d(TAG, "Service discovery success " + service); 
      AVAILABLE_NETWORKS.add(service); 

      if (!service.getServiceType().equals(SERVICE_TYPE)) { 
       Log.d(TAG, "Unknown Service Type: " + service.getServiceType()); 
      } else if (service.getServiceName().equals(mServiceName)) { 
       Log.d(TAG, "Same Machine: " + mServiceName); 
      } else if (service.getServiceName().contains(mServiceName)) { 
       Log.d(TAG, "Resolving Services: " + service); 
       mNsdManager.resolveService(service, new initializeResolveListener()); 
      } 
     } 

     @Override 
     public void onServiceLost(NsdServiceInfo service) { 
      Log.e(TAG, "service lost" + service); 
      if (ServicesAvailable.equals(service)) { 
       ServicesAvailable = null; 
      } 
     } 

     @Override 
     public void onDiscoveryStopped(String serviceType) { 
      Log.i(TAG, "Discovery stopped: " + serviceType); 
     } 

     @Override 
     public void onStartDiscoveryFailed(String serviceType, int errorCode) { 
      Log.e(TAG, "Discovery failed: Error code:" + errorCode); 
      mNsdManager.stopServiceDiscovery(this); 
     } 

     @Override 
     public void onStopDiscoveryFailed(String serviceType, int errorCode) { 
      Log.e(TAG, "Discovery failed: Error code:" + errorCode); 
      mNsdManager.stopServiceDiscovery(this); 
     } 
    }; 
} 

public class initializeResolveListener implements NsdManager.ResolveListener { 

    @Override 
    public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) { 
     Log.e(TAG, "Resolve failed " + errorCode); 
     switch (errorCode) { 
      case NsdManager.FAILURE_ALREADY_ACTIVE: 
       Log.e(TAG, "FAILURE ALREADY ACTIVE"); 
       mNsdManager.resolveService(serviceInfo, new initializeResolveListener()); 
       break; 
      case NsdManager.FAILURE_INTERNAL_ERROR: 
       Log.e(TAG, "FAILURE_INTERNAL_ERROR"); 
       break; 
      case NsdManager.FAILURE_MAX_LIMIT: 
       Log.e(TAG, "FAILURE_MAX_LIMIT"); 
       break; 
     } 
    } 

    @Override 
    public void onServiceResolved(NsdServiceInfo serviceInfo) { 
     Log.e(TAG, "Resolve Succeeded. " + serviceInfo); 


     if (serviceInfo.getServiceName().equals(mServiceName)) { 
      Log.d(TAG, "Same IP."); 
      return; 
     } 

    } 
} 

public void stopDiscovery() { 
    mNsdManager.stopServiceDiscovery(mDiscoveryListener); 
} 

public List<NsdServiceInfo> getChosenServiceInfo() { 
    return ServicesAvailable; 
} 

public void discoverServices() { 
    mNsdManager.discoverServices(
      SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener); 
} 
} 

Nadzieję, że to pomaga