This is the second part of the post. In this part I will describe the implementation of the TCP/IP Android client program. I tested these two programs by connecting two Android devices over a Wi-Fi network. The deice which host the Wi-Fi hotspot has the server program. Then I connected another Android device which has the client program to that Wi-Fi hotspot. If you want to create the server program first check
this post.
Client program has one Activity and one layout. You can download the complete client program from
here.
Demo of the client application.
Here is the code for client main activity :
package com.codeoncloud.androidclient;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import android.support.v7.app.ActionBarActivity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
public class MainActivity extends ActionBarActivity {
private TextView tvServerMessage;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvServerMessage = (TextView) findViewById(R.id.textViewServerMessage);
//Create an instance of AsyncTask
ClientAsyncTask clientAST = new ClientAsyncTask();
//Pass the server ip, port and client message to the AsyncTask
clientAST.execute(new String[] { "192.168.1.1", "8080","Hello from client" });
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* AsyncTask which handles the communication with the server
*/
class ClientAsyncTask extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params) {
String result = null;
try {
//Create a client socket and define internet address and the port of the server
Socket socket = new Socket(params[0],
Integer.parseInt(params[1]));
//Get the input stream of the client socket
InputStream is = socket.getInputStream();
//Get the output stream of the client socket
PrintWriter out = new PrintWriter(socket.getOutputStream(),true);
//Write data to the output stream of the client socket
out.println(params[2]);
//Buffer the data coming from the input stream
BufferedReader br = new BufferedReader(
new InputStreamReader(is));
//Read data in the input buffer
result = br.readLine();
//Close the client socket
socket.close();
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
@Override
protected void onPostExecute(String s) {
//Write server message to the text view
tvServerMessage.setText(s);
}
}
}
This activity will involve in three main functions.
1. Make a request to connect to the server.
2. Read the input data stream coming from the server.
3. Send data to the server.
Unlike the server program in the client program all these three tasks will be done by one AsyncTask, here named as ClientAsyncTask. An instance of the AsyncTask will be created and execution of the AsyncTask will be started in the main UI thread of the program [line 26, 28]. The internet address, the port number of and the client message pass as String parameters to the AsyncTask [line 28]. Check with your server application and change the ip address and port.
1.Make a request to connect to the server.
In the AsyncTask first client socket will be created by giving the server ip and port [line 53]. This will make a reaquest to the given server program over the Wi-Fi network since here I connected two devices using Wi-Fi hotspot.
2.Read the input data stream coming from the server.
Input stream of the client socket will be captured [line 57]. Data coming as the stream will be store in a buffer [line 63]. Data in the incoming buffer will be read line by line [line 66] and return the resulting string [line 76].
3.Send data to the server.
This is done using a Printwriter object. First data output stream of the client socket will be captured in to a Printwriter object [line 59]. Then the client message will write in to the print writer [line 61].
After completing client communication the client socket will be closed [line 68]. Then onPostExecute method of the AsyncTask will be executed and the server message will be write in to the text view [line 81].
Here is the code for main activity layout :
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.codeoncloud.androidclient.MainActivity"
tools:ignore="MergeRootFrame" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="25dp"
android:orientation="horizontal" >
<TextView
android:id="@+id/textViewsrvrMsg"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="Server msg"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=":"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="@+id/textViewServerMessage"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>
</FrameLayout>
To perform network related functions we have to grant few permissions from Manifest file.
i.e.
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
The manifest file after adding all the permissions.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.codeoncloud.androidclient"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.codeoncloud.androidclient.MainActivity"
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>
I have tested the server and client program on two Android devices connected via a Wi-Fi network. When you are testing first run the server application and then run the client application.These two applications has only the essential functionalists to complete a TCP/IP client server communication using plain java sockets. You can add your own functions to improve this program.
Happy coding :)