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 :)