How to Create Android Chat App Using Network Service Discovery(NSD) – Part II

In the previous part, we learned how to create a service and register it in the network. Now we will learn how to discover that service and connect to is using the client device.

Connecting two devices using NSD in Android
Android Network Service Discovery Chat App

Steps to connect to the server using NSD

   1. Using NSD Manager get the host IP address and Port.
   2. Send some data to the server using Socket.
   3. For bi-directional communication, client should send its IP Address to server.

Note – We can also check the data that the client has sent in the server code that we wrote in part 1, and accept or reject client connection based on it.


public class NSDClientSide extends AppCompatActivity {

 private String SERVICE_NAME = "Client Device";
 
 private String SERVICE_TYPE = "_http._tcp.";
 private InetAddress hostAddress;
 
 private int hostPort;
 private NsdManager mNsdManager;
 LinearLayout loginPanel, chatPanel;
 EditText editTextUserName, editTextAddress;
 Button buttonConnect;
 TextView chatMsg, textPort;

 EditText editTextSay;
 Button buttonSend;
 Button buttonDisconnect;

 String msgLog = "";

 ChatClientThread chatClientThread = null;

 @Override protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.client_side);
 hostPort=0;


 mNsdManager = (NsdManager) getSystemService(Context.NSD_SERVICE);
 mNsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);


 loginPanel = (LinearLayout)findViewById(R.id.loginpanel);
 chatPanel = (LinearLayout)findViewById(R.id.chatpanel);


 editTextUserName = (EditText) findViewById(R.id.username);
 editTextAddress = (EditText) findViewById(R.id.address);
 textPort = (TextView) findViewById(R.id.port);
 buttonConnect = (Button) findViewById(R.id.connect);
 textPort.setText("port: " + hostPort);
 editTextAddress.setText("Still Searching...");
 buttonDisconnect = (Button) findViewById(R.id.disconnect);
 chatMsg = (TextView) findViewById(R.id.chatmsg);


 buttonConnect.setOnClickListener(buttonConnectOnClickListener);
 buttonDisconnect.setOnClickListener(buttonDisconnectOnClickListener);


 editTextSay = (EditText)findViewById(R.id.say);
 buttonSend = (Button)findViewById(R.id.send);


 buttonSend.setOnClickListener(buttonSendOnClickListener);
 } @Override protected void onPause() {
	if (mNsdManager != null) {
	mNsdManager.stopServiceDiscovery(mDiscoveryListener);
 } super.onPause();
 }

 @Override protected void onResume() {
	super.onResume();
 if (mNsdManager != null) {
	//mNsdManager.discoverServices( // SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);
 } }

 @Override protected void onDestroy() {
	if (mNsdManager != null) {
	mNsdManager.stopServiceDiscovery(mDiscoveryListener);
 } super.onDestroy();
 }

 View.OnClickListener buttonDisconnectOnClickListener = new View.OnClickListener() {

 @Override public void onClick(View v) {
	if(chatClientThread==null){
	return;
 } chatClientThread.disconnect();
 }

 };


 View.OnClickListener buttonSendOnClickListener = new View.OnClickListener() {

 @Override public void onClick(View v) {
	if (editTextSay.getText().toString().equals("")) {
	return;
 }

 if(chatClientThread==null){
	return;
 }

 chatClientThread.sendMsg(editTextSay.getText().toString() + "n");
 }

 };


 View.OnClickListener buttonConnectOnClickListener = new View.OnClickListener() {

 @Override public void onClick(View v) {
	String textUserName = editTextUserName.getText().toString();
 if (textUserName.equals("")) {
	Toast.makeText(NSDClientSide.this, "Enter User Name", Toast.LENGTH_LONG).show();
 return;
 }

 String textAddress = editTextAddress.getText().toString();
 if (textAddress.equals("")) {
	//Toast.makeText(NSDClientSide.this, "Enter Addresse", // Toast.LENGTH_LONG).show();
 editTextAddress.setText(hostAddress.toString());
 return;
 }

 msgLog = "";
 chatMsg.setText(msgLog);
 loginPanel.setVisibility(View.GONE);
 chatPanel.setVisibility(View.VISIBLE);


 chatClientThread = new ChatClientThread( textUserName, hostAddress.getHostAddress(), hostPort);
 chatClientThread.start();
 }

 };


 NsdManager.DiscoveryListener mDiscoveryListener = new NsdManager.DiscoveryListener() {

 // Called as soon as service discovery begins. @Override public void onDiscoveryStarted(String regType) {
	Toast.makeText(NSDClientSide.this, "Discovering devices", Toast.LENGTH_SHORT).show();
 Log.d("nsdservice", "Service discovery started");
 }

 @Override public void onServiceFound(NsdServiceInfo service) {
	// A service was found! Do something with it. Log.d("nsdservice", "Service discovery success : " + service);
 Log.d("nsdservice", "Host = "+ service.getServiceName());
 Log.d("nsdservice", "port = " + String.valueOf(service.getPort()));


 Toast.makeText(NSDClientSide.this, "service found"+ service.getPort() , Toast.LENGTH_SHORT).show();


 if (!service.getServiceType().equals(SERVICE_TYPE)) {
	// Service type is the string containing the protocol and // transport layer for this service. Log.d("nsdservice", "Unknown Service Type: " + service.getServiceType());
 } else if (service.getServiceName().equals(SERVICE_NAME)) {
	//Name of the service Log.d("nsdservice", "Same machine: " + SERVICE_NAME);
 } else {
	Log.d("nsdservice", "Diff Machine : " + service.getServiceName());
 // connect to the service and obtain serviceInfo mNsdManager.resolveService(service, mResolveListener);
 } }

 @Override public void onServiceLost(NsdServiceInfo service) {
	// When the network service is no longer available. // Internal bookkeeping code goes here. Toast.makeText(NSDClientSide.this, "Service lost", Toast.LENGTH_SHORT).show();
 Log.e("nsdserviceLost", "service lost" + service);
 }

 @Override public void onDiscoveryStopped(String serviceType) {
	Toast.makeText(NSDClientSide.this, "Discovering devices stopped", Toast.LENGTH_SHORT).show();
 Log.i("nsdserviceDstopped", "Discovery stopped: " + serviceType);
 }

 @Override public void onStartDiscoveryFailed(String serviceType, int errorCode) {
	Log.e("nsdServiceSrartDfailed", "Discovery failed: Error code:" + errorCode);
 Toast.makeText(NSDClientSide.this, "Discover start failed", Toast.LENGTH_SHORT).show();
 mNsdManager.stopServiceDiscovery(this);
 }

 @Override public void onStopDiscoveryFailed(String serviceType, int errorCode) {
	Log.e("nsdserviceStopDFailed", "Discovery failed: Error code:" + errorCode);
 Toast.makeText(NSDClientSide.this, "Discover stop failed", Toast.LENGTH_SHORT).show();
 mNsdManager.stopServiceDiscovery(this);
 } };


 NsdManager.ResolveListener mResolveListener = new NsdManager.ResolveListener() {

 @Override public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
	Toast.makeText(NSDClientSide.this, "Resolve failed", Toast.LENGTH_SHORT).show();
 // Called when the resolve fails. Use the error code to debug. Log.e("nsdservicetag", "Resolve failed " + errorCode);
 Log.e("nsdservicetag", "serivce = " + serviceInfo);
 }

 @Override public void onServiceResolved(NsdServiceInfo serviceInfo) {

 Log.d("nsdservicetag", "Resolve Succeeded. " + serviceInfo);


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

 // Obtain port and IP hostPort = serviceInfo.getPort();
 hostAddress = serviceInfo.getHost();
 NSDClientSide.this.runOnUiThread(new Runnable() {

 @Override public void run() {
	editTextAddress.setText(hostAddress.getHostAddress());
 } });
 textPort.setText("port: " + hostPort);
 Toast.makeText(NSDClientSide.this, "host address = " + hostAddress.getHostAddress(), Toast.LENGTH_SHORT).show();
 } };


 private class ChatClientThread extends Thread {

 String name;
 String dstAddress;
 int dstPort;


 String msgToSend = "";
 boolean goOut = false;


 ChatClientThread(String name, String address, int port) {
	this.name = name;
 dstAddress = address;
 dstPort = port;
 }

 @Override public void run() {
	Socket socket = null;


 //Getting Local address WifiManager wm = (WifiManager) getSystemService(WIFI_SERVICE);
 String ip = Formatter.formatIpAddress(wm.getConnectionInfo().getIpAddress());


 JSONObject jsonData = new JSONObject();
 try {
	jsonData.put("request", REQUEST_CONNECT_CLIENT);
 jsonData.put("ipAddress", ip);
 jsonData.put("clientName", name);
 } catch (JSONException e) {
	e.printStackTrace();
 Log.e("nsdServicejsontag", "can't put request");
 return;
 } DataOutputStream dataOutputStream = null;
 DataInputStream dataInputStream = null;


 try {
	socket = new Socket(dstAddress, dstPort);
 dataOutputStream = new DataOutputStream( socket.getOutputStream());
 dataInputStream = new DataInputStream(socket.getInputStream());
 dataOutputStream.writeUTF(jsonData.toString());
 dataOutputStream.flush();


 while (!goOut) {
	if (dataInputStream.available() > 0) {
	msgLog += dataInputStream.readUTF();


 NSDClientSide.this.runOnUiThread(new Runnable() {

 @Override public void run() {
	chatMsg.setText(msgLog);
 } });
 }

 if(!msgToSend.equals("")){
	dataOutputStream.writeUTF(msgToSend);
 dataOutputStream.flush();
 msgToSend = "";
 } }

 } catch (UnknownHostException e) {
	e.printStackTrace();
 final String eString = e.toString();
 NSDClientSide.this.runOnUiThread(new Runnable() {

 @Override public void run() {
	Toast.makeText(NSDClientSide.this, eString, Toast.LENGTH_LONG).show();
 }

 });
 } catch (IOException e) {
	e.printStackTrace();
 final String eString = e.toString();
 NSDClientSide.this.runOnUiThread(new Runnable() {

 @Override public void run() {
	Toast.makeText(NSDClientSide.this, eString, Toast.LENGTH_LONG).show();
 }

 });
 } finally {
	if (socket != null) {
	try {
	socket.close();
 } catch (IOException e) {
	e.printStackTrace();
 } }

 if (dataOutputStream != null) {
	try {
	dataOutputStream.close();
 } catch (IOException e) {
	e.printStackTrace();
 } }

 if (dataInputStream != null) {
	try {
	dataInputStream.close();
 } catch (IOException e) {
	e.printStackTrace();
 } }

 NSDClientSide.this.runOnUiThread(new Runnable() {

 @Override public void run() {
	loginPanel.setVisibility(View.VISIBLE);
 chatPanel.setVisibility(View.GONE);
 }

 });
 }

 }

 private void sendMsg(String msg){
	msgToSend = msg;
 }

 private void disconnect(){
	goOut = true;
 } } }

Now we’ll create the Layout of our NSD Chat App:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:orientation="vertical" android:layout_width="match_parent" 
android:layout_height="match_parent">

	 <!-- <TextView 
	 android:layout_width="wrap_content" 
	 android:layout_height="wrap_content" 
	 android:layout_gravity="center_horizontal" 
	 android:autoLink="web" android:text="http://codencounters.blogspot.com/" 
	 android:textStyle="bold" />-->

	 <TextView android:layout_width="match_parent" 
	 android:layout_height="wrap_content" 
	 android:text="Chat Client" 
	 android:textStyle="bold" />

	 <LinearLayout 
	 android:id="@+id/loginpanel" 
	 android:layout_width="match_parent" 
	 android:layout_height="match_parent" 
	 android:orientation="vertical" 
	 android:visibility="visible" >

		 <EditText 
		 android:id="@+id/username" 
		 android:layout_width="match_parent" 
		 android:layout_height="wrap_content" 
		 android:hint="User name" />

		 <EditText 
		 android:id="@+id/address" 
		 android:layout_width="match_parent" 
		 android:layout_height="wrap_content" 
		 android:hint="dstAddress" />

		 <TextView android:id="@+id/port" 
		 android:layout_width="match_parent" 
		 android:layout_height="wrap_content" />

		 <Button android:id="@+id/connect" 
		  android:layout_width="match_parent" 
		  android:layout_height="wrap_content"
		  android:text="Connect..." /> 
	 </LinearLayout>

	 <LinearLayout 
	 android:id="@+id/chatpanel" 
	 android:layout_width="match_parent" 
	 android:layout_height="match_parent" 
	 android:orientation="vertical" 
	 android:visibility="gone" >

		 <EditText android:id="@+id/say"
		   android:layout_width="match_parent"
		   android:layout_height="wrap_content"
		   android:hint="Say something" />

		 <Button 
		  android:id="@+id/send" 
		  android:layout_width="match_parent" 
		  android:layout_height="wrap_content"
		  android:text="Send" />

		 <Button android:id="@+id/disconnect"
		  android:layout_width="match_parent" 
		  android:layout_height="wrap_content" 
		  android:text="Disconnect" />

		 <ScrollView
		  android:layout_width="match_parent" 
		  android:layout_height="match_parent" >

			 <TextView android:id="@+id/chatmsg"
			  android:layout_width="wrap_content" 
			  android:layout_height="wrap_content" /> 
		 </ScrollView> 
	 </LinearLayout>

</LinearLayout>

Now, the major part of out app is done! If you have any queries feel free to drop them down below. Till next time, happy coding;

Don’t miss these tips!

We don’t spam! Read our privacy policy for more info.

Sharing is caring!

4 thoughts on “How to Create Android Chat App Using Network Service Discovery(NSD) – Part II”

  1. This type of message always inspiring and I prefer to read quality content, so happy to find good place to many here in the post, the writing is just great, thanks for the post. view

Leave a Comment

Your email address will not be published.