In the 1st part, we have learned how to build the socket server and the web chat app. We also did tested the socket server using the web app.

In this part we are going to build the next important component, i.e. android chat app. The app we are about to create will have two screens. The first screen will prompt the user to enter his/her name. This name is to identify the sender whenever a message is received. The second screen is to list the chat messages and to compose a new message.

So let’s start the app by creating a new android project in Eclipse IDE.

android building chat app using java sockets

6. Building The Android Chat App

1. In Eclipse create new android project by navigating to File ⇒ New ⇒ Android Application Project and fill out all the required details.

I gave my project name as WebMobileGroupChat and package name as
info.androidhive.webgroupchat.

2. Add the below color values in res ⇒ values ⇒ colors.xml file.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="actionbar">#3cb879</color>
    <color name="body_background">#e8e8e8</color>
    <color name="body_background_green">#82e783</color>
    <color name="server_status_bar">#2b2b2b</color>
    <color name="title_gray">#434343</color>
    <color name="white">#ffffff</color>
    <color name="bg_msg_you">#5eb964</color>
    <color name="bg_msg_from">#e5e7eb</color>
    <color name="msg_border_color">#a1a1a1</color>
    <color name="bg_btn_join">#1e6258</color>
    <color name="bg_msg_input">#e8e8e8</color>
    <color name="text_msg_input">#626262</color>
    <color name="lblFromName">#777777</color>
</resources>

3. Also add the below string values in res ⇒ values ⇒ strings.xml file.

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">WebMobileGroupChat</string>
    <string name="title">(Android WebSockets Chat App)</string>
    <string name="author_name">By Ravi Tamada</string>
    <string name="author_url">www.androidhive.info</string>
    <string name="enter_name">Enter your name</string>
    <string name="btn_join">JOIN</string>
    <string name="btn_send">Send</string>

</resources>

4. Edit styles.xml located under res ⇒ values ⇒ styles.xml and add below styles. Here we are adding the styles for the action bar.

<resources>
 
    <style name="ChatAppTheme" parent="@android:style/Theme.Holo.Light">
        <item name="android:actionBarStyle">@style/MyActionBarTheme</item>
    </style>
 
    <style name="MyActionBarTheme" parent="@android:style/Widget.Holo.Light.ActionBar">
        <item name="android:background">@color/actionbar</item>
        <item name="android:titleTextStyle">@style/TitleTextStyle</item>
    </style>
    
     <style name="TitleTextStyle" parent="android:TextAppearance.Holo.Widget.ActionBar.Title">
        <item name="android:textColor">@color/white</item>
    </style>
 
</resources>

5. Now we need an activity to take the username that is required when connecting to socket server. So under res ⇒ layout folder create an xml file named activity_name.xml

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

    <ImageView
        android:id="@+id/imgLogo"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_gravity="center_horizontal"
        android:layout_marginBottom="10dp"
        android:layout_marginTop="60dp"
        android:src="@drawable/ic_launcher" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/imgLogo"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="15dp"
        android:text="@string/title"
        android:textColor="@color/white"
        android:textSize="13dp" />

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:gravity="center_horizontal"
        android:orientation="vertical"
        android:padding="20dp" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="10dp"
            android:layout_marginTop="15dp"
            android:text="@string/enter_name"
            android:textColor="@color/white"
            android:textSize="18dp" />

        <EditText
            android:id="@+id/name"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="10dp"
            android:layout_marginTop="10dp"
            android:background="@color/white"
            android:inputType="textCapWords"
            android:padding="10dp" />

        <Button
            android:id="@+id/btnJoin"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="40dp"
            android:background="@color/bg_btn_join"
            android:paddingLeft="25dp"
            android:paddingRight="25dp"
            android:text="@string/btn_join"
            android:textColor="@color/white" />
    </LinearLayout>

    <!-- author info -->

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="20dp"
        android:gravity="center_horizontal"
        android:orientation="vertical" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/author_name"
            android:textColor="@color/white"
            android:textSize="12dp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/author_url"
            android:textColor="@color/white"
            android:textSize="12dp" />
    </LinearLayout>

</RelativeLayout>

6. Create a new activity named NameActivity.java under project’s main package. In this activity we don’t handle anything complex. We just take the user input from EditText and send it to other activity.

package info.androidhive.webgroupchat;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class NameActivity extends Activity {

	private Button btnJoin;
	private EditText txtName;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_name);

		btnJoin = (Button) findViewById(R.id.btnJoin);
		txtName = (EditText) findViewById(R.id.name);

		// Hiding the action bar
		getActionBar().hide();

		btnJoin.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				if (txtName.getText().toString().trim().length() > 0) {

					String name = txtName.getText().toString().trim();

					Intent intent = new Intent(NameActivity.this,
							MainActivity.class);
					intent.putExtra("name", name);

					startActivity(intent);

				} else {
					Toast.makeText(getApplicationContext(),
							"Please enter your name", Toast.LENGTH_LONG).show();
				}
			}
		});
	}
}

7. Finally make NameActivity.java as launcher activity in AndroidManifest.xml. Also add INTERNET permission as we need to make internet calls. This is how your manifest file should look like.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="info.androidhive.webgroupchat"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="13"
        android:targetSdkVersion="21" />

    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/ChatAppTheme" >
        <activity
            android:name=".NameActivity"
            android:label="@string/app_name"
            android:windowSoftInputMode="adjustPan" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".MainActivity"
            android:screenOrientation="portrait" >
        </activity>
    </application>

</manifest>

After doing the above changes, if you run the app, you should see the name activity launched as first activity. Below is the output of name activity where user can enter their name and move to next activity.

android building chat app using java sockets

Before going to implement sockets, I would like to create few resource files first which required to create messages interface.

8. Download this background image and paste it in project’s res ⇒ drawable folder. (If you don’t see drawable folder, create a new one and name it as drawable). This image will be used as background repeat image for the chat conversation.

9. Create 3 new xml files under drawable folder named tile_bg.xml, bg_msg_from.xml and bg_msg_you.xml and add below codes. These drawable xml files are used as background for chat messages.

<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
  android:src="@drawable/bg_messages" 
  android:tileMode="repeat" />
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >

    <!-- view background color -->
    <solid android:color="@color/bg_msg_from" >
    </solid>

    <corners android:radius="5dp" >
    </corners>

</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >

    <!-- view background color -->
    <solid android:color="@color/bg_msg_you" >
    </solid>

    <corners android:radius="5dp" >
    </corners>

</shape>

10. Now under res ⇒ layout folder create two more xml files named list_item_message_left.xml and list_item_message_right.xml. These two layout files are used to align chat messages on left and right in the list view.

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

    <TextView
        android:id="@+id/lblMsgFrom"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="12dp"
        android:textColor="@color/lblFromName"
        android:textStyle="italic" 
        android:padding="5dp"/>

    <TextView
        android:id="@+id/txtMsg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="16dp"
        android:layout_marginRight="80dp"
        android:textColor="@color/title_gray"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:paddingTop="5dp"
        android:paddingBottom="5dp"
        android:background="@drawable/bg_msg_from"/>

</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="right"
    android:orientation="vertical"
    android:paddingBottom="5dp"
    android:paddingRight="10dp"
    android:paddingTop="5dp" >

    <TextView
        android:id="@+id/lblMsgFrom"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="5dp"
        android:textColor="@color/lblFromName"
        android:textSize="12dp"
        android:textStyle="italic" />

    <TextView
        android:id="@+id/txtMsg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="80dp"
        android:background="@drawable/bg_msg_you"
        android:paddingBottom="5dp"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:paddingTop="5dp"
        android:textColor="@color/white"
        android:textSize="16dp" />

</LinearLayout>

11. Now we need to create another layout to list all the chat messages and an option to compose a new message. Create another layout activity_main.xml and add below code.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/tile_bg"
    android:orientation="vertical" >

    <ListView
        android:id="@+id/list_view_messages"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="@null"
        android:divider="@null"
        android:transcriptMode="alwaysScroll" 
        android:stackFromBottom="true">
    </ListView>

    <LinearLayout
        android:id="@+id/llMsgCompose"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="@color/white"
        android:orientation="horizontal"
        android:weightSum="3" >

        <EditText
            android:id="@+id/inputMsg"
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="2"
            android:background="@color/bg_msg_input"
            android:textColor="@color/text_msg_input"
            android:paddingLeft="6dp"
            android:paddingRight="6dp"/>

        <Button
            android:id="@+id/btnSend"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@color/bg_btn_join"
            android:textColor="@color/white" 
            android:text="@string/btn_send" />
    </LinearLayout>

</LinearLayout>

12. With the above step, the creation of layout resources is done. Now we’ll quickly create few helper classes. In your project create a new package and name it as other.

After creating the new package my package name will be info.androidhive.webgroupchat.other.

13. In other package, create a class named Utils.java and add below code. This class contains methods to save the user’s session id in shared preferences.

package info.androidhive.webgroupchat.other;

import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;

public class Utils {

	private Context context;
	private SharedPreferences sharedPref;

	private static final String KEY_SHARED_PREF = "ANDROID_WEB_CHAT";
	private static final int KEY_MODE_PRIVATE = 0;
	private static final String KEY_SESSION_ID = "sessionId",
			FLAG_MESSAGE = "message";

	public Utils(Context context) {
		this.context = context;
		sharedPref = this.context.getSharedPreferences(KEY_SHARED_PREF,
				KEY_MODE_PRIVATE);
	}

	public void storeSessionId(String sessionId) {
		Editor editor = sharedPref.edit();
		editor.putString(KEY_SESSION_ID, sessionId);
		editor.commit();
	}

	public String getSessionId() {
		return sharedPref.getString(KEY_SESSION_ID, null);
	}

	public String getSendMessageJSON(String message) {
		String json = null;

		try {
			JSONObject jObj = new JSONObject();
			jObj.put("flag", FLAG_MESSAGE);
			jObj.put("sessionId", getSessionId());
			jObj.put("message", message);

			json = jObj.toString();
		} catch (JSONException e) {
			e.printStackTrace();
		}

		return json;
	}

}

14. Create another class named Message.java. This model class defines each chat message where it contains message id, text and a boolean flag (isSelf) to define message owner. Using this boolean flag we’ll align message left or right in the list view.

package info.androidhive.webgroupchat.other;

public class Message {
	private String fromName, message;
	private boolean isSelf;

	public Message() {
	}

	public Message(String fromName, String message, boolean isSelf) {
		this.fromName = fromName;
		this.message = message;
		this.isSelf = isSelf;
	}

	public String getFromName() {
		return fromName;
	}

	public void setFromName(String fromName) {
		this.fromName = fromName;
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

	public boolean isSelf() {
		return isSelf;
	}

	public void setSelf(boolean isSelf) {
		this.isSelf = isSelf;
	}

}

15. Create a class named WsConfig.java. This is where we define socket configuration i.e the socket url, port number and end point.

package info.androidhive.webgroupchat.other;

public class WsConfig {
	public static final String URL_WEBSOCKET = "ws://192.168.0.102:8080/WebMobileGroupChatServer/chat?name=";
}

16. Now under your main package create a class named MessagesListAdapter.java to implement the custom list view adapter class. This class plays a major role in rendering the list by aligning the chat messages left or right.

package info.androidhive.webgroupchat;

import info.androidhive.webgroupchat.other.Message;

import java.util.List;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

public class MessagesListAdapter extends BaseAdapter {

	private Context context;
	private List<Message> messagesItems;

	public MessagesListAdapter(Context context, List<Message> navDrawerItems) {
		this.context = context;
		this.messagesItems = navDrawerItems;
	}

	@Override
	public int getCount() {
		return messagesItems.size();
	}

	@Override
	public Object getItem(int position) {
		return messagesItems.get(position);
	}

	@Override
	public long getItemId(int position) {
		return position;
	}

	@SuppressLint("InflateParams")
	@Override
	public View getView(int position, View convertView, ViewGroup parent) {

		/**
		 * The following list not implemented reusable list items as list items
		 * are showing incorrect data Add the solution if you have one
		 * */

		Message m = messagesItems.get(position);

		LayoutInflater mInflater = (LayoutInflater) context
				.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);

		// Identifying the message owner
		if (messagesItems.get(position).isSelf()) {
			// message belongs to you, so load the right aligned layout
			convertView = mInflater.inflate(R.layout.list_item_message_right,
					null);
		} else {
			// message belongs to other person, load the left aligned layout
			convertView = mInflater.inflate(R.layout.list_item_message_left,
					null);
		}

		TextView lblFrom = (TextView) convertView.findViewById(R.id.lblMsgFrom);
		TextView txtMsg = (TextView) convertView.findViewById(R.id.txtMsg);

		txtMsg.setText(m.getMessage());
		lblFrom.setText(m.getFromName());

		return convertView;
	}
}

17. Download the android websockets library and extract somewhere. Thanks to Koush for writing such a useful library.

18. Import the downloaded android websockets library into Eclipse workspace. Goto File ⇒ Import ⇒ Android ⇒ Existing Android Code Into Workspace and select the downloaded library project home directory.

19. Now add this project as a Library to our project. Right Click on project ⇒ Properties ⇒ Android (on left) ⇒ Add (on right, under Library section) and select the imported project.

android-adding-library-project

20. Finally open the main activity class (MainActivity.java) do the below changes. The below code very simple and everything is self explanatory.

> A web socket is created using WebSocketClient class and it has all the callback methods like onConnect, onMessage and onDisconnect.

> In onMessage method parseMessage() is called to parse the JSON received from the socket server.

> In parseMessage() method, the purpose of JSON is identified by reading the flag value.

> When a new message is received, the message is added to list view data source and adapter.notifyDataSetChanged() is called to update the chat list.

> sendMessageToServer() method is used to send the message from android device to socket server.

> playBeep() method is called to play device’s default notification sound whenever a new message is received.

package info.androidhive.webgroupchat;

import info.androidhive.webgroupchat.other.Message;
import info.androidhive.webgroupchat.other.Utils;
import info.androidhive.webgroupchat.other.WsConfig;

import java.net.URI;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.content.Intent;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;

import com.codebutler.android_websockets.WebSocketClient;

public class MainActivity extends Activity {

	// LogCat tag
	private static final String TAG = MainActivity.class.getSimpleName();

	private Button btnSend;
	private EditText inputMsg;

	private WebSocketClient client;

	// Chat messages list adapter
	private MessagesListAdapter adapter;
	private List<Message> listMessages;
	private ListView listViewMessages;

	private Utils utils;

	// Client name
	private String name = null;

	// JSON flags to identify the kind of JSON response
	private static final String TAG_SELF = "self", TAG_NEW = "new",
			TAG_MESSAGE = "message", TAG_EXIT = "exit";

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		btnSend = (Button) findViewById(R.id.btnSend);
		inputMsg = (EditText) findViewById(R.id.inputMsg);
		listViewMessages = (ListView) findViewById(R.id.list_view_messages);

		utils = new Utils(getApplicationContext());

		// Getting the person name from previous screen
		Intent i = getIntent();
		name = i.getStringExtra("name");

		btnSend.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				// Sending message to web socket server
				sendMessageToServer(utils.getSendMessageJSON(inputMsg.getText()
						.toString()));

				// Clearing the input filed once message was sent
				inputMsg.setText("");
			}
		});

		listMessages = new ArrayList<Message>();

		adapter = new MessagesListAdapter(this, listMessages);
		listViewMessages.setAdapter(adapter);

		/**
		 * Creating web socket client. This will have callback methods
		 * */
		client = new WebSocketClient(URI.create(WsConfig.URL_WEBSOCKET
				+ URLEncoder.encode(name)), new WebSocketClient.Listener() {
			@Override
			public void onConnect() {

			}

			/**
			 * On receiving the message from web socket server
			 * */
			@Override
			public void onMessage(String message) {
				Log.d(TAG, String.format("Got string message! %s", message));

				parseMessage(message);

			}

			@Override
			public void onMessage(byte[] data) {
				Log.d(TAG, String.format("Got binary message! %s",
						bytesToHex(data)));

				// Message will be in JSON format
				parseMessage(bytesToHex(data));
			}

			/**
			 * Called when the connection is terminated
			 * */
			@Override
			public void onDisconnect(int code, String reason) {

				String message = String.format(Locale.US,
						"Disconnected! Code: %d Reason: %s", code, reason);

				showToast(message);

				// clear the session id from shared preferences
				utils.storeSessionId(null);
			}

			@Override
			public void onError(Exception error) {
				Log.e(TAG, "Error! : " + error);

				showToast("Error! : " + error);
			}

		}, null);

		client.connect();
	}

	/**
	 * Method to send message to web socket server
	 * */
	private void sendMessageToServer(String message) {
		if (client != null && client.isConnected()) {
			client.send(message);
		}
	}

	/**
	 * Parsing the JSON message received from server The intent of message will
	 * be identified by JSON node 'flag'. flag = self, message belongs to the
	 * person. flag = new, a new person joined the conversation. flag = message,
	 * a new message received from server. flag = exit, somebody left the
	 * conversation.
	 * */
	private void parseMessage(final String msg) {

		try {
			JSONObject jObj = new JSONObject(msg);

			// JSON node 'flag'
			String flag = jObj.getString("flag");

			// if flag is 'self', this JSON contains session id
			if (flag.equalsIgnoreCase(TAG_SELF)) {

				String sessionId = jObj.getString("sessionId");

				// Save the session id in shared preferences
				utils.storeSessionId(sessionId);

				Log.e(TAG, "Your session id: " + utils.getSessionId());

			} else if (flag.equalsIgnoreCase(TAG_NEW)) {
				// If the flag is 'new', new person joined the room
				String name = jObj.getString("name");
				String message = jObj.getString("message");

				// number of people online
				String onlineCount = jObj.getString("onlineCount");

				showToast(name + message + ". Currently " + onlineCount
						+ " people online!");

			} else if (flag.equalsIgnoreCase(TAG_MESSAGE)) {
				// if the flag is 'message', new message received
				String fromName = name;
				String message = jObj.getString("message");
				String sessionId = jObj.getString("sessionId");
				boolean isSelf = true;

				// Checking if the message was sent by you
				if (!sessionId.equals(utils.getSessionId())) {
					fromName = jObj.getString("name");
					isSelf = false;
				}

				Message m = new Message(fromName, message, isSelf);

				// Appending the message to chat list
				appendMessage(m);

			} else if (flag.equalsIgnoreCase(TAG_EXIT)) {
				// If the flag is 'exit', somebody left the conversation
				String name = jObj.getString("name");
				String message = jObj.getString("message");

				showToast(name + message);
			}

		} catch (JSONException e) {
			e.printStackTrace();
		}

	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		
		if(client != null & client.isConnected()){
			client.disconnect();
		}
	}

	/**
	 * Appending message to list view
	 * */
	private void appendMessage(final Message m) {
		runOnUiThread(new Runnable() {

			@Override
			public void run() {
				listMessages.add(m);

				adapter.notifyDataSetChanged();

				// Playing device's notification
				playBeep();
			}
		});
	}

	private void showToast(final String message) {

		runOnUiThread(new Runnable() {

			@Override
			public void run() {
				Toast.makeText(getApplicationContext(), message,
						Toast.LENGTH_LONG).show();
			}
		});

	}

	/**
	 * Plays device's default notification sound
	 * */
	public void playBeep() {

		try {
			Uri notification = RingtoneManager
					.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
			Ringtone r = RingtoneManager.getRingtone(getApplicationContext(),
					notification);
			r.play();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();

	public static String bytesToHex(byte[] bytes) {
		char[] hexChars = new char[bytes.length * 2];
		for (int j = 0; j < bytes.length; j++) {
			int v = bytes[j] & 0xFF;
			hexChars[j * 2] = hexArray[v >>> 4];
			hexChars[j * 2 + 1] = hexArray[v & 0x0F];
		}
		return new String(hexChars);
	}

}

Now if you run the app, you can see the below screen as main activity output.

android building chat app like whatsapp

With this we have completed the android app part too.

7. Testing the Web and Android App

To test the android app you need two android mobiles or you can just use one android mobile and a web app. Follow below steps to test the android app.

1. Make sure that all your devices are connected to same wifi network. If you are using two android mobiles, connect them to same wifi network.

2. Get the ip address of the machine on which socket server is running. Follow 2nd step in Part1 tutorial to get the ip address of your machine.

3. Replace the ip address in WsConfig.java and main.js with your machine IP address.

4. Deploy the app on to android devices. If you are testing the app using web and android apps, open both the apps and test.

android-building-the-chat-app

The same conversation can be seen on web app too.

androd-chat-app-dad-mom-son

I hope everyone could able to build the app without any hurdles. If you have any queries or suggestions, please do let me know in the comment section below.

Ravi is hardcore Android programmer and Android programming has been his passion since he compiled his first hello-world program. Solving real problems of Android developers through tutorials has always been interesting part for him.
  • Sébastien Kondov

    Great tutorial 🙂 Long time i wanted to see that. Thank you

  • Marcos Campos

    rav você é foda!

  • moez

    Hey thanks bro, but i would ask something How can i store & retrieve image in database table (MySQL) especially when i use listview with user picture .

    • Alex

      in the server mysql to store the URL of the image stored in your server, after the client with android you just fetch the url and download the image

      • moez

        But i don’t want to use url
        Just tables.

  • mahdi

    How to chat between two android with internet 3g or 2g

  • Malaika Khan

    Ravi please share the link of your videos thanks

  • Ulhas Patil

    Wow Great Tutorial Ravi…..
    Ravi don’t you have video tutorials to get more knowledge..?
    Please share the link of them…

    • Sorry Ulhas, I don’t have video tutorials!

      • Ulhas Patil

        Thanks Ravi for your Reply..,
        If you are Planning to do that in future then Please Please let us know…

        Thanks in Advance…. 🙂

      • Shan

        What if we want to android to android chat please guide

  • Venkata Prasad

    Thanks Ravi,
    From long time, I am looking for this.

  • jp

    I get as far as trying to run the server and get 404.

    HTTP Status 404 – /WebMobileGroupChatServer/

    type Status report

    message /WebMobileGroupChatServer/

    description The requested resource is not available.

    • jp

      from stackoverflow, this solved it for me,

      Click on Window > Show view > Server OR right click on the server in “Servers” view, select “Properties”.
      In the “General” panel, click on the “Switch Location” button.
      The “Location: [workspace metadata]” should replace by something else.
      Open the Overview screen for the server by double clicking it.
      In the Server locations tab , select “Use Tomcat location”.
      Save the configurations and restart the Server.

  • Ray

    Excellent work man, Got it all up and running in less than an hour with next to no java / droid experience. If you would like some paid work please get in touch.

  • Guest

    How To Set it up for godaddy hosting ??

    • You need to check their checklist whether they are providing sockets support or not.

  • Mohd Riyas

    totally error in android app project..!! give me a solution??

  • you can use socket.io ! node.js instead of TCP scoket! for backend!

  • daksh

    Hi Ravi

    Thanks for the tutorial, can we use PHP as server side instead of java ?

  • Srikanth Munaga

    Then how we can do if they are using different Ip’s

  • Andrew

    Is it possible for you to make some material design tutorials

  • Naveed

    Brilliant tutorial, can there be a login and register sytem? it would be wonderful!

  • Alex

    Great tutorial! Works fine, but i have one error when username is in cyrillic.

    For name “Алексей”, serverside threw to me this:
    __
    SEVERE: Servlet.service() for servlet [default] in context with path [/WebMobileGroupChatServer] threw exception
    java.lang.IllegalArgumentException: java.net.URISyntaxException: Illegal character in query at index 37: /WebMobileGroupChatServer/chat?name=???»?µ?????µ??
    __

    In mobile app I’ve tried to edit code in Main.activity and replace URLEncoder.encode(name) with URLEncoder.encode(name, “UTF-8”) , but it doesn’t help me =

    Any suggestions how to solve it?(

  • Arken

    We can make it work on desktop? Any suggest?

  • Kelvin

    i am getting the following error

    org.apache.http.client.HttpResponseException: Not Found

    any clue what the issue would be?

  • Raja Sekaran

    Great Tutorial..but better we need php in server side..Thanks anna..

  • Brom

    so good but I want save all chat history.

  • Dwi Marstya Wibowo

    Dear Ravi, how i can create more chat room ?
    Thanks

  • Juan

    Ravi, can you do some tutorials about Fragments? i say, i googled a lot about fragments tutorials(more than, for example, creating fragment tabs, post and show SQLite results to a ListView in one of those fragments, etc), really i need to know how to mannage this type of programming…a lot of people have problems to show things in the fragments and play with it…because now the fragments are better than more activities in one application, so..pleaseee

    • Levi Costa

      +1

  • Allay Khalil

    Hy i have implemented this tutorial its fine and working well on same laptop in two diffrent browser like (Google and firefox)but problem is there when i want to test this app web to mobile or mobile to mobile on same wifi connection because i’p address of android device and laptop are different , how i can test this app web to android mobile or two different device on same wife connection

    • Riz

      u must make one laptop to become server then on the same conecction such as wifi connection then on android code set ip with ip localhost laptop as server.

  • Allay Khalil

    Kindly email me with your answer in my mailbox (allaykhalil@gmail.com)

    or any one how can give me answer

  • J TechCentral

    Have you heard about Pars I’m using it for a chat apllication I am making https://parse.com/products/android

    • Levi Costa

      How it works?

    • dan li

      I tried it. it’s cool,with some delay

  • khalil b

    public class Ravi extends India implement code{
    public void main (String args[]){
    system.out.println(“Hello RAVI , you are Genious “);
    }
    }

    • mamadou pathé diallo

      Really awesome RAVI.

      He is such a great guy

      • Thank you 🙂

        • Khalil Serano

          can anyone help me ?

  • Dan

    hi Ravi,
    I import the project and followed all steps suggested here. I want communication between two android phones. I connected both of them with the same router. but I’m getting the error as below:
    “Error! : java.net.ConnectException: failed to connect to /192.168.x.x(port80): connect failed: ETIMEOUT(connection timeout)”. Is there anything that i’m missing?

    Anyone here who got the same error?! and successful to solve it?

    ~Thanks 🙂

  • janaki

    hi Ravi, how to integrate stickers in chat app .as my project needs stickers

  • okan

    can we add push notifications to this system with gcm ?

  • Дархан Журсин

    Hello everyone! can I change words to my native language?

    • Sumit

      Use Google translation

  • Kostas

    Is there any way to make it run only through android app without using desktop versions?

  • maniteja

    Hi,

    Thanks for your tutorial.

    here (webSocket.onopen ) is not firing when i am running the application.can you help me where i did the mistake.
    I am using eclipse j2ee and java version 1.6.

  • Rajendra

    Hi Ravi do you know how we can do android video chat(like this tutorial does text/image chat). What i want to do is the application like facetime. Is it possible do develop that application using android? Could you provide some opensource/sample or point to the right direction. Thankyou

  • Attaaa

    Hi,i follow your tutorial very nicee and thank you…i am new developer i want to make silent apps…i just want to make a button when i click on it my mobile going to silent mode and when i again press it will come in a normal mode..please plzz if u have any code about it..

  • Aman Gupta

    Hey Ravi,

    Thanks for amazing tutorial, I have used this trick for using node.js but my application is unable to get onMessage callback when some thing is returned to socket from node. Can you please help me out with this trouble.

    Thanks in advance.

  • Sumit

    Hey Ravi,
    I think this code works when the MainActivity is in foreground, do you have any idea how to maintain connection persistent through out the app, I am developing a chat application using SignalR android client and facing the above problem, i have defined connection in service class, but the problem is i every time i get the message i need to broadcast them to particular activity or fragment . Any better idea that this. Thanks in advance.

  • NIMA

    hi Ravi

    I import the project and followed all steps suggested here. I want
    communication between two android phones. I connected both of them with
    the same router. but I’m getting the error as below:
    “Error! :
    java.net.ConnectException: failed to connect to /192.168.x.x(port80):
    connect failed: ETIMEOUT(connection timeout)”. Is there anything that
    i’m missing?

    • prashant

      dude change the ip accordingly. not the ravi’s one.

  • کاظم از شیراز

    I import the project and followed all steps suggested here. I want
    communication between two android phones. I connected both of them with
    the same router. but I’m getting the error as below:
    “Error! :
    java.net.ConnectException: failed to connect to /192.168.x.x(port80):
    connect failed: ETIMEOUT(connection timeout)”. Is there anything that
    i’m missing?

    • What is the ip address of your system that is running tomcat server?

      • Joy

        samee error plz help me i changed my ip in WsConfig.java and main.js.i want to chat betwen two android app only plz help

  • 荣城 李

    I finished the Project following the above steps.But it’s found that my R file was lost.Dose there anyone have the same question.Forgive my Chinglish,thank you!

    • In Eclipse, go to Project -> Clean. It will generate R file again. Make sure that you don’t have any errors in xml files.

    • dan li

      Chinglish?haha.好不容易遇见中国人呢

  • smithy14

    Hi Ravi, great tutorial and worked perfectly.
    It would be great to know how would I go about transferring the server side onto a live server?

  • Jelqui

    Thank you this tutorial is amazing! and easy to understand +100

  • Duy

    how about I want to make an other is not the same Wifi network?

  • peoce

    Thank you very much. the tuition is very awesome. It’s helps my a lot.

  • kalle

    thanks for this great tutorial, but i have a question, i want to run this on my local Ubuntu server and access it with my mobile phone. if i run this programm over my pc it is running but when i start it over the server i get “Error! : org.apache.http.client.HttpResponseException: Not Found” what should i do?

    • thenoelb

      I’m having the same problem.

      • alex

        i have the same problem…. but i guess its the library socket

        • Omar

          i have same problem , what do you mean by the library socket ?
          is there is something that the host server doesn’t support comparing to localhost or what ?

    • Omar

      Hello kalle, I have this problem exactly when upload to my hosting also .
      did you find any solution ?

  • kláda

    So this application works only if devices are on same network ?
    Right ?

    • If you host the project online, it works like whatsapp over internet.

      • So, if i host this project in a server, say example.com, then what would be the web socket addrs instead “”ws://192.168.0.102:8080/WebMobileGroupChatServer/chat?name=” . ?

        • It would be ws://example.com/chat?name=” . ? (Assuming WebMobileGroupChatServer is home directory for example.com)

          • Ohkey dude 🙂

          • Wander Martinez

            how you solved, could you explain to me, I’m stuck there?

          • i heard that sockets works only in dedicated servers.
            I’m not sure about that.i just heard.

            The project worked fine for me when i put the project in my local tomcat server and gave my IP (ipconfig-cmd) in the socket address.

          • cannot connect to websocket. 🙁 help me

          • so where’s the port number and ip ??

  • Hanan Lipskin

    i’m having some troubleshoot with this app (i guess its something really simple that i missed), could someone please help me out on skype?
    please?

  • eric

    Hi Ravi, Thank you very much for this tutorial

    I want to send data to particular user using sockets.

    I am working on application were i need to send some data to specific user without much of delay. Actualy I have more then 1000 users who are online out of those I want to select one user and send the data to him only.

    I had two solution

    1.current implementation=>

    So far I am using push notification for this purpose I get the user’s device Id and send notification to him but problem is push notification(sending/receiving) depend on my server and GCM server so it get delayed sometime(I observed sometime it gets delayed by 5 min also).

    2.Not implemented=>

    Another option is to run thread continuously to check any msg is arrived, if arrived check if whether is meant for same user or not,if he is targeted user then show the data else discard .But here also problem is even if this msg dose not belong to that user one need to check the condition and then discard.

    Do you have a solution ?

    thanks in advance

  • Guest

    Hi Ravi, Thank you very much for this tutorial.
    I want to display the emotion in message. can you give me someways to do. 🙂

  • Rauzan

    hello ravi i cannot open webSocket = new WebSocket(“ws://” + socket_url + “:” + port

    + “/WebMobileGroupChatServer/chat?name=” + name);

    i use alert(WebSocket);

    and alert is undefined;

    please help me.

    • I guess the variable name is case sensitive. Call alert(webSocket); (w is small letter)

  • Hi Ravi. I’m trying to send pictures using this chat. I’m doing as follows:
    Transform the bitmap image in String, create a new flag called photo and send to the server. I managed to send very small pictures, but when I send photos of 5 MB it gives an error saying that the text is too large and can not be sent by parts. Do you have any solution for this?

  • Hosein

    hi ravi
    your tuts is so good,tanx for that
    i want to develop a video app
    but i cant find good reference or good tutarial for that
    can u say what can i do?
    tnx so much!!!

    • can you tell me more about your app, what video app? is it like youtube?

      • Hosein

        No thats like viber or line video call
        may app is a chat app for contact between a company persons

        • I think cometchat, arrowchat and etc. may help you.
          you can create this with javascript and html in cordova platform

  • thank you, i wait for you to complete this project and create a full features chat application.

  • Khalil Serano

    i have problems on NameActivity.java on these 3 lines : setContentView(R.layout.activity_name);

    btnJoin = (Button) findViewById(R.id.btnJoin);

    txtName = (EditText) findViewById(R.id.name);

    and other problem on activity_main.xml on this line : android:text=”@string/hello_world” />

    • Aditi

      I’m also getting same problem. Are u able to resolve it ?

      • Khalil Serano

        unfortunately not

    • Abeer Ali

      Replace android:text=”@string/hello_world” with android:text=”Hello World”

      • Khalil Serano

        okay

  • James

    Thanks so much. That’s what I need 🙂

  • Yamini

    Hello Ravi, Thanks for this great tutorial, but i have a question, i want to run this on my local server and access it with my mobile phone. if i run this program over my pc it is running but when i start it over the server i get “Error! : org.apache.http.client.HttpResponseException: Not Found” what should i do? Please Help me

    • Omar

      Hello , I have this problem exactly when upload to my hosting also .
      did you find any solution ?

  • Hey Ravi, i hosted the WebMobileGroupChatServer . but its not connecting to the websocket.

  • Wander Martinez

    Hello, good guide. I did everything work locally but now I would like to upload it to my hosting, example.com. Now that door and I have to put ip? could you explain why I get this error: org.apache.http.client.httpresponseexception: not found.
    I loaded the whole folder in my hosting server, but I can not to communicate. I tried to get on the web and funciona everything but not in the mobile app.
    help me please

    • Omar

      Hello , I have this problem exactly when upload to my hosting also .
      did you find any solution ?

  • SID MALLAH

    how to make NameActivity.java as launcher activity in AndroidManifest.xml.

    any one please explain me pleaseee

    • Talha

      put this code in the activity tag of your desired launch activity in your manifest.

  • Guest

    This application is working fine in the wifi or lan when i converted to mobile data its not working may i know the changes required to make it work on everywhere??

    • Talha

      I think you will have to upload your server side code on a proper server with hosting and all, so that you can use the app when ever you want.

  • window iam

    how to image send ?

  • I noticed that you’re initializing LayoutInflater in getView() of MessageListAdapter.
    I think it will initialize the inflater when getView get called,isn’t?
    So my quistion is – “Can we initialize the inflater in the Constructor??”,”Does it cause any problems in future?”

  • Guest

    onMesssage() is not listening to my incoming message

  • Kadir Abdul

    how to send ping and receive pong ?

  • Furkan Çetinkaya

    download code link problem help me ?

  • hi, I’ve gotten the app to work and the mobile website to work. Now i would like to use it to where a user doesn’t have to be connected to my network to chat. I’m assuming I have “host the project on a website” I have http://www.clxxxii.com How can i host it to my site. DO i just host the index page or the whole project. I’ve never done this before?

  • Bilal Halayqa

    Cannot download in both part’s links 🙁 please help …

  • susheel

    does this app allos to chat with pople on different netorks?

  • Ravi, I want to add a parameter an extra parameter..

    sendMessageToServer(utils.getSendMessageJSONXD(inputMsg

    .getText().toString(), superString), superString);

    see.. superString is the value i want to dictate which picture to show. I check my shared preferences tp check which picture to show.

    superString = (sharedPrefs.getString(“prefSyncAvatar”, “1”));

    so say if the value for superString = (sharedPrefs.getString(“prefSyncAvatar”, “1”)); was.. 4

    then i want to build the message.. to show a particular picture according to the number sent by the server..

    I’ve added a constructor with the values from the FB tutorial.

    // Message m = new Message(fromName, message, isSelf);

    Message m = new Message(fromName, message, isSelf, id, name,

    image, status, profilePic, timeStamp, url);

    when i try to pass a value to

    String id = jObj.getString(“id”);

    but id is null

    public String getSendMessageJSONXD(String message, String whichPicIndex) {

    String json = null;

    try {

    JSONObject jObj = new JSONObject();

    jObj.put(“flag”, FLAG_MESSAGE);

    jObj.put(“sessionId”, getSessionId());

    jObj.put(“message”, message);

    jObj.put(“id”, id);

    json = jObj.toString();

    } catch (JSONException e) {

    e.printStackTrace();

    }

    return json;

    }

  • Aditi

    Hi Ravi,
    I’m getting 2 errors in the WebMobileGroupChat section.
    1. in res -> values-v11->styles.xml

    error: Error retrieving parent for item: No resource found that matches the given name
    ‘Theme.AppCompat.Light’.

    2. R value cannot be resolved. I’ve done every possible solution available on the internet, but it is not working. Finally, I used ctrl+shift+O to import required files, but R file isn’t there in the gen folder and also it has further generated lots of new errors.

    Kindly revert back!

  • Dhina19

    how i create multiple groups

  • Mohit

    Hello Ravi,

    Can you tell me how to make the java server.

    I mean , suppose if i have a website -www.abc.com ..

    Then, how to make these java j2ee files working on the web server.

    I have not done it before.

    Thanks in advance.

    • Install Apache Tomcat server in your hosting or in your VPS. Then Export the web application as WAR file from Eclipse. Open apache tomcat manager console in your browser. Deploy the WAR file. Now you can use your web application from your server link 🙂 I hope it helps.

  • Ali

    how to add group chat in this application
    any help ??

  • Avinash Pandey

    i am done with web chat application.Its working correctly,but when i was trying to import your android project with web socket libraryin my workspace,its showing many errors.how to resove it?