Android NSD not discovering all services

后端 未结 6 601
慢半拍i
慢半拍i 2021-02-02 08:24

I\'m trying to run an application using Android Native Service Discovery but sometimes when I run the application, it doesn\'t discover all services from my network. I\'m runnin

相关标签:
6条回答
  • 2021-02-02 08:45

    I tend to think the whole NSD implementation in Android must be a bit flaky. I also have a simple Activity just to demonstrate the lifecycle (no Sockets are opened), and sometimes it works, and sometimes it does not work. I simply don't get it. Here is the Activity if anybody has some insight:

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

    On the other hand, Wifi Direct based NSD seems to be very reliable for me:

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

    Note that neither of these Activities have any resources, so just add the Activities to your Manifest with the proper permissions.

    0 讨论(0)
  • 2021-02-02 08:47

    I was seeing the same issue with devices not being discovered and was able to fix it by acquiring the WifiManager Multicast lock prior to discovering services:

    val multicastLock: WifiManager.MulticastLock = (mContext.getSystemService(Context.WIFI_SERVICE) as WifiManager).createMulticastLock(TAG)
    multicastLock.setReferenceCounted(true)
    
    multicastLock.acquire()
    
    mNsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener)
    

    And later releasing the lock when done discovering services:

    mNsdManager.stopServiceDiscovery(mDiscoveryListener)
    
    multicastLock.release()
    
    0 讨论(0)
  • 2021-02-02 08:50

    To discover all services of the connected network just change the service type you are discovering,

    public static final String SERVICE_TYPE = "_services._dns-sd._udp";
    
    0 讨论(0)
  • 2021-02-02 08:51

    I had the same issue, reinstall helped. Try to use:)

    0 讨论(0)
  • 2021-02-02 08:51

    It may be little late for the answer, but I found a good solution for NSD for android give on their developer site. I made a few modification and it works perfectly fine.

    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);
    }
    }
    

    Hope it this helps

    0 讨论(0)
  • 2021-02-02 09:05

    I'm afraid that there are still bugs in the implementation that cause it to miss services. I've done a couple days of testing with multiple Android devices and a MacBook, and it just doesn't work all the time. I documented my findings on a bug report over in the Android bug tracker: https://code.google.com/p/android/issues/detail?id=178080

    0 讨论(0)
提交回复
热议问题