Server Client Communication in android

S

In this tutorial we will make a TCP Connection. The server will be written in Java and the client will be written in Android. Actually it will be a very simple messenger client.

A. Make the Server in Java

1.To create the server create a new project in Java and make a class called “TCPServer”. In this class put the following code:

import javax.swing.*;

import java.io.*;

import java.net.ServerSocket;

import java.net.Socket;

/* The class extends the Thread class so we can receive and send messages at the same time*/

public class TCPServer extends Thread {


public static final int SERVERPORT = 4444;

private boolean running = false;

private PrintWriter mOut;

private OnMessageReceived messageListener;

public static void main(String[] args) {

//opens the window where the messages will be received and sent

ServerBoard frame = new ServerBoard();

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.pack();

frame.setVisible(true);

}

/**Constructor of the class @param messageListener listens for the messages*/

public TCPServer(OnMessageReceived messageListener) {

this.messageListener = messageListener;

}

/* Method to send the messages from server to client @param message the message sent by the server*/

public void sendMessage(String message){

if (mOut != null && !mOut.checkError()) {

mOut.println(message);

mOut.flush();

}

}

@Override

public void run() {

super.run();

running = true;

try {

System.out.println(“S: Connecting…”);


//create a server socket. A server socket waits for requests to come in over the network.

ServerSocket serverSocket = new ServerSocket(SERVERPORT);

//create client socket… the method accept() listens for a connection to be made to this socket //and accepts it.

Socket client = serverSocket.accept();

System.out.println(“S: Receiving…”);


try {

//sends the message to the client

mOut = new PrintWriter(new BufferedWriter(new OutputStreamWriter(client.getOutputStream())), true);

//read the message received from client

BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));

//in this while we wait to receive messages from client (it’s an infinite loop)

//this while it’s like a listener for messages

while (running) {

String message = in.readLine();

if (message != null && messageListener != null) {

//call the method messageReceived from ServerBoard class

messageListener.messageReceived(message);

}

}

} catch (Exception e) {

System.out.println(“S: Error”);

e.printStackTrace();

} finally {

client.close();

System.out.println(“S: Done.”);

}


} catch (Exception e) {

System.out.println(“S: Error”);

e.printStackTrace();

}

}

//Declare the interface. The method messageReceived(String message) will must be implemented in the ServerBoard

//class at on startServer button click

public interface OnMessageReceived {

public void messageReceived(String message);

}

}

2.Now create another java class and call it “ServerBoard”. In this class we will make the “messenger” UI (a very simple one) with a field where the messages will be added, a text field where the server side can enter a message and 2 buttons: one to start the connection and one to send the messages. The code is like this:

import javax.swing.*;

import java.awt.*;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

public class ServerBoard extends JFrame {

private JTextArea messagesArea;

private JButton sendButton;

private JTextField message;

private JButton startServer;

private TCPServer mServer;


public ServerBoard() {


super(“ServerBoard”);

JPanel panelFields = new JPanel();

panelFields.setLayout(new BoxLayout(panelFields,BoxLayout.X_AXIS));

JPanel panelFields2 = new JPanel();

panelFields2.setLayout(new BoxLayout(panelFields2,BoxLayout.X_AXIS));

//here we will have the text messages screen

messagesArea = new JTextArea();

messagesArea.setColumns(30);

messagesArea.setRows(10);

messagesArea.setEditable(false);

sendButton = new JButton(“Send”);

sendButton.addActionListener(new ActionListener() {

@Override

public void actionPerformed(ActionEvent e) {

// get the message from the text view

String messageText = message.getText();

// add message to the message area

messagesArea.append(“n” + messageText);

// send the message to the client

mServer.sendMessage(messageText);

// clear text

message.setText(“”);

}

});

startServer = new JButton(“Start”);

startServer.addActionListener(new ActionListener() {

@Override

public void actionPerformed(ActionEvent e) {

// disable the start button

startServer.setEnabled(false);


//creates the object OnMessageReceived asked by the TCPServer constructor

mServer = new TCPServer(new TCPServer.OnMessageReceived() {

@Override

//this method declared in the interface from TCPServer class is implemented here

//this method is actually a callback method, because it will run every time when it will be called from

//TCPServer class (at while)

public void messageReceived(String message) {

messagesArea.append(“n “+message);

}

});

mServer.start();

}

});

//the box where the user enters the text (EditText is called in Android)

message = new JTextField();

message.setSize(200, 20);


//add the buttons and the text fields to the panel

panelFields.add(messagesArea);

panelFields.add(startServer);

panelFields2.add(message);

panelFields2.add(sendButton);


getContentPane().add(panelFields);

getContentPane().add(panelFields2);

getContentPane().setLayout(new BoxLayout(getContentPane(),BoxLayout.Y_AXIS));

setSize(300, 170);

setVisible(true);

}

}

B. Create the Client in Android

/*To create the Client, create a new project and call the class that creates with the project ”   MyActivity”.

*After this make a new class and call it “TCPClient”

*Now in the class TCPClient put the following code:*/


1.

import android.util.Log;

import java.io.*;

import java.net.InetAddress;

import java.net.Socket;

public class TCPClient {

private String serverMessage;

public static final String SERVERIP = “192.168.0.102”; //your computer IP address

public static final int SERVERPORT = 4444;

private OnMessageReceived mMessageListener = null;

private boolean mRun = false;

PrintWriter out;

BufferedReader in;

/* Constructor of the class. OnMessagedReceived listens for the messages received from server*/

public TCPClient(OnMessageReceived listener) {

mMessageListener = listener;

}

/** Sends the message entered by client to the server

* @param message text entered by client*/

public void sendMessage(String message){

if (out != null && !out.checkError()) {

out.println(message);

out.flush();

}

}

public void stopClient(){

mRun = false;

}

public void run() {

mRun = true;

try {

//here you must put your computer’s IP address.

InetAddress serverAddr = InetAddress.getByName(SERVERIP);

Log.e(“TCP Client”, “C: Connecting…”);

//create a socket to make the connection with the server

Socket socket = new Socket(serverAddr, SERVERPORT);

try {

//send the message to the server

out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);

Log.e(“TCP Client”, “C: Sent.”);

Log.e(“TCP Client”, “C: Done.”);

//receive the message which the server sends back

in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

//in this while the client listens for the messages sent by the server

while (mRun) {

serverMessage = in.readLine();

if (serverMessage != null && mMessageListener != null) {

//call the method messageReceived from MyActivity class

mMessageListener.messageReceived(serverMessage);

}

serverMessage = null;

}

Log.e(“RESPONSE FROM SERVER”, “S: Received Message: ‘” + serverMessage + “‘”);

} catch (Exception e) {

Log.e(“TCP”, “S: Error”, e);

} finally {

//the socket must be closed. It is not possible to reconnect to this socket

// after it is closed, which means a new socket instance has to be created.

socket.close();

}

} catch (Exception e) {

Log.e(“TCP”, “C: Error”, e);

}

}

//Declare the interface. The method messageReceived(String message) will must be implemented in the MyActivity

//class at on asynckTask doInBackground

public interface OnMessageReceived {

public void messageReceived(String message);

}

}

At the beginning of this class you have a constant SERVERIP. In this constant you have to put your computer IPv4. To do this open the commander and type ipconfig and press Enter. Then you will see your computer’s IP.

Also the SERVERPORT from this class (TCPClient) must be the same with the SERVERPORT from server class (TCPServer).

Now that the server and client classes are done, we have to set the interface a little. For this we will make a ListView in MyActivity class where we will get the messages sent and received, an EditText to enter the message from client side and a button to send the message. So let’s begin.

2.go to res – layout – main.xml and put this code in main.xml:

<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”

android:orientation=”vertical”

android:layout_width=”fill_parent”

android:layout_height=”fill_parent”>

<ListView android:id=”@+id/list”

android:layout_width=”fill_parent”

android:layout_height=”0dip”

android:layout_weight=”1″

android:transcriptMode=”alwaysScroll”

android:cacheColorHint=”#00000000″

android:listSelector=”@android:color/transparent”/>

<LinearLayout android:id=”@+id/footer”

android:layout_width=”fill_parent”

android:layout_height=”wrap_content”

android:orientation=”horizontal”

android:gravity=”bottom”>

<EditText android:inputType=”textMultiLine|textNoSuggestions”

android:layout_width=”0dp”

android:layout_height=”40dp”

android:id=”@+id/editText”

android:layout_weight=”1″/>

<Button android:layout_width=”wrap_content”

android:layout_height=”wrap_content”

android:id=”@+id/send_button”

android:layout_gravity=”center_vertical”

android:text=”send” />

</LinearLayout>

</LinearLayout>

create a new xml file and call it “list_item.xml”. This will contain a TextView for the messages which will be added to the ListView. The code will look like this:

3.<?xml version=”1.0″ encoding=”utf-8″?>

<LinearLayout

xmlns:android=”http://schemas.android.com/apk/res/android”

android:orientation=”horizontal”

android:layout_width=”fill_parent”

android:layout_height=”fill_parent”

android:id=”@+id/list_item”

android:gravity=”center_vertical”>

<TextView android:layout_width=”wrap_content”

android:layout_height=”wrap_content”

android:id=”@+id/list_item_text_view”

android:textSize=”20sp”

android:padding=”10dp”

android:layout_marginLeft=”5dp”/>

</LinearLayout>

4.create a new class and call it “MyCustomAdapter”.

import android.content.Context;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.BaseAdapter;

import android.widget.TextView;

import java.util.ArrayList;

public class MyCustomAdapter extends BaseAdapter {

private ArrayList<String> mListItems;

private LayoutInflater mLayoutInflater;

public MyCustomAdapter(Context context, ArrayList<String> arrayList){

mListItems = arrayList;

//get the layout inflater

mLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

}

@Override

public int getCount() {

//getCount() represents how many items are in the list

return mListItems.size();

}

@Override

//get the data of an item from a specific position

//i represents the position of the item in the list

public Object getItem(int i) {

return null;

}

@Override

//get the position id of the item from the list

public long getItemId(int i) {

return 0;

}

@Override

public View getView(int position, View view, ViewGroup viewGroup) {

//check to see if the reused view is null or not, if is not null then reuse it

if (view == null) {

view = mLayoutInflater.inflate(R.layout.list_item, null);

}

//get the string item from the position “position” from array list to put it on the TextView

String stringItem = mListItems.get(position);

if (stringItem != null) {

TextView itemName = (TextView) view.findViewById(R.id.list_item_text_view);

if (itemName != null) {

//set the item name on the TextView

itemName.setText(stringItem);

}

}

//this method must return the view corresponding to the data at the specified position.

return view;

}

}

5.And now in the MyActivity class put the following code:

import android.app.Activity;

import android.os.AsyncTask;

import android.os.Bundle;

import android.view.View;

import android.widget.Button;

import android.widget.EditText;

import android.widget.ListView;

import java.util.ArrayList;

public class MyActivity extends Activity

{

private ListView mList;

private ArrayList<String> arrayList;

private MyCustomAdapter mAdapter;

private TCPClient mTcpClient;

@Override

public void onCreate(Bundle savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

arrayList = new ArrayList<String>();

final EditText editText = (EditText) findViewById(R.id.editText);

Button send = (Button)findViewById(R.id.send_button);

//relate the listView from java to the one created in xml

mList = (ListView)findViewById(R.id.list);

mAdapter = new MyCustomAdapter(this, arrayList);

mList.setAdapter(mAdapter);

// connect to the server

new connectTask().execute(“”);

send.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

String message = editText.getText().toString();

//add the text in the arrayList

arrayList.add(“c: ” + message);

//sends the message to the server

if (mTcpClient != null) {

mTcpClient.sendMessage(message);

}

//refresh the list

mAdapter.notifyDataSetChanged();

editText.setText(“”);

}

});

}

public class connectTask extends AsyncTask<String,String,TCPClient> {

@Override

protected TCPClient doInBackground(String… message) {

//we create a TCPClient object and

mTcpClient = new TCPClient(new TCPClient.OnMessageReceived() {

@Override

//here the messageReceived method is implemented

public void messageReceived(String message) {

//this method calls the onProgressUpdate

publishProgress(message);

}

});

mTcpClient.run();

return null;

}

@Override

protected void onProgressUpdate(String… values) {

super.onProgressUpdate(values);

//in the arrayList we add the messaged received from server

arrayList.add(values[0]);

// notify the adapter that the data set has changed. This means that new message received

// from server was added to the list

mAdapter.notifyDataSetChanged();

}

}

}

6.And one last thing. Go to AndroidManifest.xml and put the internet permission just before the </manifest>:

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


7.

  • Now that the project is done we must see how it actually works

1. First, you must open the server, so run the TCPServer class, the one that is made in Java and a window called ServerBoard will appear. Press on the start button like in the picture below. Do NOT start the android project before you press the start button!



 

2. The server waits the client to connect now, so run the android project on the emulator and wait for the project to load.

 

3. After the project is loaded enter a message in the EditText and send it. Your text should appear on the ListView.

 

4. Now go back to the ServerBoard and send a message to the client from Android. The message from server side should appear on the ListView too.

 

NOTE: If you test this on a device and it's not working, probably you should turn off all your firewall (from Windows, from antivirus) . And make sure that your device WIFI is turned on (because the android client must be on the same network as the server).

 

 

 

 

 

 

 

 

 

About the author

prashant.koli
By prashant.koli

Category