[postad]
2. Create a java class named “Constants”. The code for this class is below:
/**
* Description
*
* @author Catalin Prata
* Date: 2/12/13
*/
public class Constants {
public static final String CLOSED_CONNECTION = "kazy_closed_connection";
public static final String LOGIN_NAME = "kazy_login_name";
}
3. Create another class called “TcpServer”. The code for this class is below:
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
*
* @author Catalin Prata
* Date: 2/12/13
*/
public class TcpServer extends Thread {
public static final int SERVERPORT = 4444;
// while this is true the server will run
private boolean running = false;
// used to send messages
private PrintWriter bufferSender;
// callback used to notify new messages received
private OnMessageReceived messageListener;
private ServerSocket serverSocket;
private Socket client;
/**
* Constructor of the class
*
* @param messageListener listens for the messages
*/
public TcpServer(OnMessageReceived messageListener) {
this.messageListener = messageListener;
}
public static void main(String[] args) {
//opens the window where the messages will be received and sent
MainScreen frame = new MainScreen();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
/**
* Close the server
*/
public void close() {
running = false;
if (bufferSender != null) {
bufferSender.flush();
bufferSender.close();
bufferSender = null;
}
try {
client.close();
serverSocket.close();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("S: Done.");
serverSocket = null;
client = null;
}
/**
* Method to send the messages from server to client
*
* @param message the message sent by the server
*/
public void sendMessage(String message) {
if (bufferSender != null && !bufferSender.checkError()) {
bufferSender.println(message);
bufferSender.flush();
}
}
public boolean hasCommand(String message) {
if (message != null) {
if (message.contains(Constants.CLOSED_CONNECTION)) {
messageListener.messageReceived(message.replaceAll(Constants.CLOSED_CONNECTION, "") + " disconnected from room.");
// close the server connection if we have this command and rebuild a new one
close();
runServer();
return true;
} else if (message.contains(Constants.LOGIN_NAME)) {
messageListener.messageReceived(message.replaceAll(Constants.LOGIN_NAME, "") + " connected to room.");
return true;
}
}
return false;
}
/**
* Builds a new server connection
*/
private void runServer() {
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 = new ServerSocket(SERVERPORT);
//create client socket... the method accept() listens for a connection to be made to this socket and accepts it.
client = serverSocket.accept();
System.out.println("S: Receiving...");
try {
//sends the message to the client
bufferSender = 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 = null;
try {
message = in.readLine();
} catch (IOException e) {
System.out.println("Error reading message: " + e.getMessage());
}
if (hasCommand(message)) {
continue;
}
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();
}
} catch (Exception e) {
System.out.println("S: Error");
e.printStackTrace();
}
}
@Override
public void run() {
super.run();
runServer();
}
//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);
}
}
4. Create a new java class class called “MainScreen”. The code for this class is below:
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* Description
*
* @author Catalin Prata
* Date: 2/12/13
*/
public class MainScreen extends JFrame {
private JTextArea messagesArea;
private JButton sendButton;
private JTextField message;
private JButton startServer;
private JButton stopServer;
private TcpServer mServer;
public MainScreen() {
super("MainScreen");
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);
if (mServer != null) {
// 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) {
//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();
// disable the start button and enable the stop one
startServer.setEnabled(false);
stopServer.setEnabled(true);
}
});
stopServer = new JButton("Stop");
stopServer.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (mServer != null) {
mServer.close();
}
// disable the stop button and enable the start one
startServer.setEnabled(true);
stopServer.setEnabled(false);
}
});
//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);
panelFields.add(stopServer);
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);
}
}
TCP CLIENT IN ANDROID
1. Create an xml file under res – layout and name it “list_item”. The code for this xml file is below:
<?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>
2. In main.xml file (the one which is generated by IDE) put the following code:
<?xml version="1.0" encoding="utf-8"?>
<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"/>
<!-- send button -->
<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>
3. If you don’t have the “menu” directory under res – menu, you should create one and after it’s done, create a new xml file called “main_menu.xml” in the menu directory. Ā Then put the following code:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/connect" android:title="Connect"/>
<item android:id="@+id/disconnect" android:title="Disconnect" android:enabled="false"/>
</menu>
4. Now you have to create the java classes (in the src directory). The first class that you have to create is the activity class. So create a new java class and name it ClientActivity. The code for the activity is below:
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import java.util.ArrayList;
public class ClientActivity extends Activity {
private ListView mList;
private ArrayList<String> arrayList;
private ClientListAdapter 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 ClientListAdapter(this, arrayList);
mList.setAdapter(mAdapter);
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("");
}
});
}
@Override
protected void onPause() {
super.onPause();
// disconnect
mTcpClient.stopClient();
mTcpClient = null;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_menu, menu);
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
if (mTcpClient != null) {
// if the client is connected, enable the connect button and disable the disconnect one
menu.getItem(1).setEnabled(true);
menu.getItem(0).setEnabled(false);
} else {
// if the client is disconnected, enable the disconnect button and disable the connect one
menu.getItem(1).setEnabled(false);
menu.getItem(0).setEnabled(true);
}
return super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.connect:
// connect to the server
new ConnectTask().execute("");
return true;
case R.id.disconnect:
// disconnect
mTcpClient.stopClient();
mTcpClient = null;
// clear the data set
arrayList.clear();
// notify the adapter that the data set has changed.
mAdapter.notifyDataSetChanged();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
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();
}
}
}
5. Now create another java class and call it ClientListAdapter. The code is just below:
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;
/**
* Description
*
* @author Catalin Prata
* Date: 2/12/13
*/
public class ClientListAdapter extends BaseAdapter {
private ArrayList<String> mListItems;
private LayoutInflater mLayoutInflater;
public ClientListAdapter(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;
}
}
6. Create another java class called TcpClient.Ā
import android.util.Log;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
/**
* Description
*
* @author Catalin Prata
* Date: 2/12/13
*/
public class TcpClient {
public static final String SERVER_IP = "192.168.0.100"; //your computer IP address
public static final int SERVER_PORT = 4444;
// message to send to the server
private String mServerMessage;
// sends message received notifications
private OnMessageReceived mMessageListener = null;
// while this is true, the server will continue running
private boolean mRun = false;
// used to send messages
private PrintWriter mBufferOut;
// used to read messages from the server
private BufferedReader mBufferIn;
/**
* 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 (mBufferOut != null && !mBufferOut.checkError()) {
mBufferOut.println(message);
mBufferOut.flush();
}
}
/**
* Close the connection and release the members
*/
public void stopClient() {
// send mesage that we are closing the connection
sendMessage(Constants.CLOSED_CONNECTION+"Kazy");
mRun = false;
if (mBufferOut != null) {
mBufferOut.flush();
mBufferOut.close();
}
mMessageListener = null;
mBufferIn = null;
mBufferOut = null;
mServerMessage = null;
}
public void run() {
mRun = true;
try {
//here you must put your computer's IP address.
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
Log.e("TCP Client", "C: Connecting...");
//create a socket to make the connection with the server
Socket socket = new Socket(serverAddr, SERVER_PORT);
try {
//sends the message to the server
mBufferOut = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
//receives the message which the server sends back
mBufferIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// send login name
sendMessage(Constants.LOGIN_NAME+"Kazy");
//in this while the client listens for the messages sent by the server
while (mRun) {
mServerMessage = mBufferIn.readLine();
if (mServerMessage != null && mMessageListener != null) {
//call the method messageReceived from MyActivity class
mMessageListener.messageReceived(mServerMessage);
}
}
Log.e("RESPONSE FROM SERVER", "S: Received Message: '" + mServerMessage + "'");
} 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);
}
}
7. Be sure that you AndroidManifest.xml file contains the Internet permission. The code for AndroidManifest is below:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="YOUR_PACKAGE"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="8"/>
<uses-permission android:name="android.permission.INTERNET" />
<application android:label="@string/app_name">
<activity
android:name="ClientActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
If you need more exaplanations about TCP connection you can read theĀ old TCP Connection Tutorial. There are more details.
I hope this tutorial helped you :D
