Search code examples
javaandroidnsd

NsdManager fails to register service on android


I'm trying to register a nsdservice on android using the NsdManager but it keeps failing because of internal errors, whatever that means. this is just a test, in the future i want to be able to connect multiple devices to one "hostdevice". the clients should be able to send data to the host. Notice that i tried previously to set the host inetadress to the devices ip in the network, which yielded the same result.

my mainactivity:

public class Main2Activity extends AppCompatActivity {

ServerSocket serverSocket;
int localPort;
NsdManager.RegistrationListener registrationListener;
String serviceName = "ef";
NsdManager nsdManager;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main2);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            try {
                initializeServerSocket();
                initializeRegistrationListener();
                registerService(localPort);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    });
}

@SuppressWarnings("deprecation")
public void registerService (int port) throws UnknownHostException {
    NsdServiceInfo serviceInfo  = new NsdServiceInfo();

    serviceInfo.setServiceName("testchat");
    serviceInfo.setServiceType("nsdchat._tcp");
    serviceInfo.setPort(port);

    /*WifiManager wm = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE);
    int ipAdress = wm.getConnectionInfo().getIpAddress();

    serviceInfo.setHost(InetAddress.getByName(Formatter.formatIpAddress(ipAdress)));*/

    nsdManager = (NsdManager) this.getSystemService(Context.NSD_SERVICE);

    Log.d("nsdmanager", "info: " + nsdManager.toString());

    nsdManager.registerService(
            serviceInfo, NsdManager.PROTOCOL_DNS_SD, registrationListener);
}

public void initializeServerSocket() throws IOException {
    // Initialize a server socket on the next available port.
    serverSocket = new ServerSocket(0);

    // Store the chosen port.
    localPort =  serverSocket.getLocalPort();

    Log.d("test", "initialized server socket: " + localPort);
}

public void initializeRegistrationListener() {
    registrationListener = new NsdManager.RegistrationListener() {

        @Override
        public void onServiceRegistered(NsdServiceInfo NsdServiceInfo) {
            // Save the service name.  Android may have changed it in order to
            // resolve a conflict, so update the name you initially requested
            // with the name Android actually used.
            Log.d("test", "service registered");
            serviceName = NsdServiceInfo.getServiceName();
        }

        @Override
        public void onRegistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
            // Registration failed!  Put debugging code here to determine why.
            Log.d("test", "registration failed");
            Log.d("serviceinfo", serviceInfo.toString());
            switch (errorCode) {
                case NsdManager.FAILURE_ALREADY_ACTIVE:
                    Log.d("test", "FAILURE_ALREADY_ACTIVE");
                    break;
                case NsdManager.FAILURE_INTERNAL_ERROR:
                    Log.d("test", "FAILURE_INTERNAL_ERROR");
                    break;
                case NsdManager.FAILURE_MAX_LIMIT:
                    Log.d("test", "FAILURE_MAX_LIMIT");
                    break;
            }
        }

        @Override
        public void onServiceUnregistered(NsdServiceInfo arg0) {
            // Service has been unregistered.  This only happens when you call
            // NsdManager.unregisterService() and pass in this listener.
        }

        @Override
        public void onUnregistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
            // Unregistration failed.  Put debugging code here to determine why.
        }
    };
    Log.d("test", "initialized registration listener");
}

My Log looks like this:

06-06 14:23:57.016 16319-16319/xxx D/test: initialized server socket: 49575
06-06 14:23:57.016 16319-16319/xxx D/test: initialized registration listener
06-06 14:23:57.020 16319-16319/xxx D/nsdmanager: info: android.net.nsd.NsdManager@a7f4c86
06-06 14:23:57.030 16319-16457/xxx D/test: registration failed
06-06 14:23:57.031 16319-16457/xxx D/serviceinfo: name: testchat, type: nsdchat._tcp, host: null, port: 49575, txtRecord: 
06-06 14:23:57.031 16319-16457/xxx D/test: FAILURE_INTERNAL_ERROR

Solution

  • A little modify than the code can work.

    Change the

    serviceInfo.setServiceType("nsdchat._tcp"); 
    

    to

    serviceInfo.setServiceType("_nsdchat._tcp"); 
    

    than registration success.

    From the Android document: https://developer.android.com/training/connect-devices-wirelessly/nsd.html

    The second parameter sets the service type, specifies which protocol and transport layer the application uses. The syntax is "_<protocol>._<transportlayer>"