Hi all, Today I will show you how you can implement Client-Server architecture in an Android environment.
Watch Video Demo
Below is the demo of the app we are going to build.
Watch Video Tutorial
I wil be explaining the code in the below video tutorial. If you have any comments, please leave it below the video in the comments section.
What is a socket?
A socket is an interface between application and network. The socket type dictates the style of communication reliable vs. best effort connection-oriented vs. connectionless. Once configured the application can pass data to the socket for network transmission receive data from the socket (transmitted through the network by some other host).
A socket is a software end-point of an application.
By using a Socket a process in one system can communicate with another process in a system.
Lets see here how we can do this in Android.
I have two projects here. One is a Server program and other one is the Client.
Once you run both programs in two different devices. You need to Start the server in the Server device first. Then Client device will send a message to connect and it gets connected. Once it is connected, that means that a socket connection is established. Now you can send messages in both directions using this Socket Connection.
Note : To Connect between sockets, both devices has to be in the same network (for eg : same Wi-Fi).
Also you have to replace the IP in the client program with the server IP (Or this will be your actual server IP with the opened port specifically for communication with your device).You can find the IP of an Android device by navigating to the Wifi Settings -> Menu -> Advanced.
Add permission
<uses-permission android:name="android.permission.INTERNET" />
Server
Layout
This will contain a button to start the server and another button to send a message to the server.
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_server" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="20dp" tools:context=".ServerActivity"> <Button android:id="@+id/start_server" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:onClick="onClick" android:text="Start Server" /> <EditText android:id="@+id/edMessage" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/start_server" android:layout_marginTop="5dp" android:layout_marginBottom="5dp" android:text="Message from Server" /> <ScrollView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_above="@+id/send_data" android:layout_below="@+id/edMessage"> <LinearLayout android:id="@+id/msgList" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical"> </LinearLayout> </ScrollView> <Button android:id="@+id/send_data" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:background="@drawable/button_pressed" android:onClick="onClick" android:text="Send Message to Client" android:textColor="@android:color/white" /> </RelativeLayout>
Server Activity
We are going to build the Server App first, so this will be the MainActivity for this project.
package com.coderzheaven.clientserverdemo; import android.graphics.Color; import android.os.Bundle; import android.os.Handler; import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.TextView; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.text.SimpleDateFormat; import java.util.Date; public class ServerActivity extends AppCompatActivity implements View.OnClickListener { private ServerSocket serverSocket; private Socket tempClientSocket; Thread serverThread = null; public static final int SERVER_PORT = 3003; private LinearLayout msgList; private Handler handler; private int greenColor; private EditText edMessage; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_server); setTitle("Server"); greenColor = ContextCompat.getColor(this, R.color.green); handler = new Handler(); msgList = findViewById(R.id.msgList); edMessage = findViewById(R.id.edMessage); } public TextView textView(String message, int color) { if (null == message || message.trim().isEmpty()) { message = "<Empty Message>"; } TextView tv = new TextView(this); tv.setTextColor(color); tv.setText(message + " [" + getTime() +"]"); tv.setTextSize(20); tv.setPadding(0, 5, 0, 0); return tv; } public void showMessage(final String message, final int color) { handler.post(new Runnable() { @Override public void run() { msgList.addView(textView(message, color)); } }); } @Override public void onClick(View view) { if (view.getId() == R.id.start_server) { msgList.removeAllViews(); showMessage("Server Started.", Color.BLACK); this.serverThread = new Thread(new ServerThread()); this.serverThread.start(); return; } if (view.getId() == R.id.send_data) { String msg = edMessage.getText().toString().trim(); showMessage("Server : " + msg, Color.BLUE); sendMessage(msg); } } private void sendMessage(final String message) { try { if (null != tempClientSocket) { new Thread(new Runnable() { @Override public void run() { PrintWriter out = null; try { out = new PrintWriter(new BufferedWriter( new OutputStreamWriter(tempClientSocket.getOutputStream())), true); } catch (IOException e) { e.printStackTrace(); } out.println(message); } }).start(); } } catch (Exception e) { e.printStackTrace(); } } class ServerThread implements Runnable { public void run() { Socket socket; try { serverSocket = new ServerSocket(SERVER_PORT); findViewById(R.id.start_server).setVisibility(View.GONE); } catch (IOException e) { e.printStackTrace(); showMessage("Error Starting Server : " + e.getMessage(), Color.RED); } if (null != serverSocket) { while (!Thread.currentThread().isInterrupted()) { try { socket = serverSocket.accept(); CommunicationThread commThread = new CommunicationThread(socket); new Thread(commThread).start(); } catch (IOException e) { e.printStackTrace(); showMessage("Error Communicating to Client :" + e.getMessage(), Color.RED); } } } } } class CommunicationThread implements Runnable { private Socket clientSocket; private BufferedReader input; public CommunicationThread(Socket clientSocket) { this.clientSocket = clientSocket; tempClientSocket = clientSocket; try { this.input = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream())); } catch (IOException e) { e.printStackTrace(); showMessage("Error Connecting to Client!!", Color.RED); } showMessage("Connected to Client!!", greenColor); } public void run() { while (!Thread.currentThread().isInterrupted()) { try { String read = input.readLine(); if (null == read || "Disconnect".contentEquals(read)) { Thread.interrupted(); read = "Client Disconnected"; showMessage("Client : " + read, greenColor); break; } showMessage("Client : " + read, greenColor); } catch (IOException e) { e.printStackTrace(); } } } } String getTime() { SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); return sdf.format(new Date()); } @Override protected void onDestroy() { super.onDestroy(); if (null != serverThread) { sendMessage("Disconnect"); serverThread.interrupt(); serverThread = null; } } }
Client
Now that server is done, we are going to create files for the client project. Make sure both are different projects for better understanding.
Layout
Client Layout will contain a button to send a message to server.
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/activity_server" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="20dp"> <Button android:id="@+id/connect_server" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:onClick="onClick" android:text="Connect to server" /> <EditText android:id="@+id/edMessage" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/connect_server" android:layout_marginTop="5dp" android:layout_marginBottom="5dp" android:text="Message from Client" /> <ScrollView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_above="@+id/send_data" android:layout_below="@+id/edMessage"> <LinearLayout android:id="@+id/msgList" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" /> </ScrollView> <Button android:id="@+id/send_data" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:background="@drawable/button_pressed" android:onClick="onClick" android:text="Send Message to server" android:textColor="@android:color/white" /> </RelativeLayout>
Client Activity
package com.coderzheaven.clientapplication; import android.graphics.Color; import android.os.Bundle; import android.os.Handler; import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.TextView; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; import java.text.SimpleDateFormat; import java.util.Date; public class ClientActivity extends AppCompatActivity implements View.OnClickListener { public static final int SERVERPORT = 3003; public static final String SERVER_IP = "YOUR_SERVER_IP"; private ClientThread clientThread; private Thread thread; private LinearLayout msgList; private Handler handler; private int clientTextColor; private EditText edMessage; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_client); setTitle("Client"); clientTextColor = ContextCompat.getColor(this, R.color.green); handler = new Handler(); msgList = findViewById(R.id.msgList); edMessage = findViewById(R.id.edMessage); } public TextView textView(String message, int color) { if (null == message || message.trim().isEmpty()) { message = "<Empty Message>"; } TextView tv = new TextView(this); tv.setTextColor(color); tv.setText(message + " [" + getTime() + "]"); tv.setTextSize(20); tv.setPadding(0, 5, 0, 0); return tv; } public void showMessage(final String message, final int color) { handler.post(new Runnable() { @Override public void run() { msgList.addView(textView(message, color)); } }); } @Override public void onClick(View view) { if (view.getId() == R.id.connect_server) { msgList.removeAllViews(); showMessage("Connecting to Server...", clientTextColor); clientThread = new ClientThread(); thread = new Thread(clientThread); thread.start(); showMessage("Connected to Server...", clientTextColor); return; } if (view.getId() == R.id.send_data) { String clientMessage = edMessage.getText().toString().trim(); showMessage(clientMessage, Color.BLUE); if (null != clientThread) { clientThread.sendMessage(clientMessage); } } } class ClientThread implements Runnable { private Socket socket; private BufferedReader input; @Override public void run() { try { InetAddress serverAddr = InetAddress.getByName(SERVER_IP); socket = new Socket(serverAddr, SERVERPORT); while (!Thread.currentThread().isInterrupted()) { this.input = new BufferedReader(new InputStreamReader(socket.getInputStream())); String message = input.readLine(); if (null == message || "Disconnect".contentEquals(message)) { Thread.interrupted(); message = "Server Disconnected."; showMessage(message, Color.RED); break; } showMessage("Server: " + message, clientTextColor); } } catch (UnknownHostException e1) { e1.printStackTrace(); } catch (IOException e1) { e1.printStackTrace(); } } void sendMessage(final String message) { new Thread(new Runnable() { @Override public void run() { try { if (null != socket) { PrintWriter out = new PrintWriter(new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())), true); out.println(message); } } catch (Exception e) { e.printStackTrace(); } } }).start(); } } String getTime() { SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); return sdf.format(new Date()); } @Override protected void onDestroy() { super.onDestroy(); if (null != clientThread) { clientThread.sendMessage("Disconnect"); clientThread = null; } } }
If Client or Server exits, it sends a “Disconnect” command. By this way the peer will know that the other process has disconnected.
Source Code
https://github.com/MrVipinVijayan/android-client-server
Thanks for reading. Please leave your valuable comments below.
Medium: https://vipinvijayannair.medium.com
Facebook: https://www.facebook.com/contactvipinvijayan
Twitter: @mr_vipin_nair
Page: https://www.facebook.com/Mobile-Tutor-299932940922778
Hi, James, This is great!,
but i have 1 question,
for example if i want to make the textview message received replaced by the new message without print it to the next line, what should i do?
Ezra,
You could just go a messageTv.setText() on the textview instead of messageTv.append().
Hi,
Is it possible to connect two devices from different networks, please?
Yes, it is possible, but you network should allow outbound connections through that specific port.
Hi thanks a lot for your example code.
I have a one question.
There is your code “socket = serverSocket.accept();”
That’s where the code doesn’t work.
What can I do?
cogoree, What is the error you are getting? You port should allow the socket connection and if not you should be in the same wifi network.
I am also having issue from this code , is there any solution here. It doesn’t log any things.
Dilip, What is the issue you are facing?
There is no error the code just stop executing after this line.
can I use this code by creating a hotspot in the device I’m using as server?
how would you change your server code if the server was a raspberry pi?
the client is android
amy,
Sorry, I am not aware of that.
Nothing happening.
It shows Only Starting Server…
I have changed the IP Address in both Server and Client App with my Server Device IP address. But not working.
Are you on the same Wifi Network or you should have a PORT open for communication.
Same Wifi Network , changed the server IP Address , compileSdkVersion 25, buildToolsVersion “25.0.2”
There are no errors, but nothing happening.!!! I do not know why it does not work.
Do I need to request additional Java programs as the version is upgraded?
Please help me
Hi,
I changed the IP Address in both Server and Client App and using same WiFi network
But nothing happening.
classpath ‘com.android.tools.build:gradle:2.2.3’ compileSdkVersion 25
buildToolsVersion “25.0.2” do not know why it does not work.
Is it possible that the version is up and that system approval is needed?
please answer about my question.
Hi,
I changed the IP Address in both Server and Client App and using same WiFi network
But nothing happening.
classpath ‘com.android.tools.build:gradle:2.2.3’ compileSdkVersion 25
buildToolsVersion “25.0.2” do not know why it does not work.
Is it possible that the version is up and that system approval is needed?
please answer about my question.
Are you using the port that is allowed and not a reserved one like 8080 for http?
Hello thank you for this post … But when i try to send a message (for exemple : “hey i’m here” in clientThread.sendmessage(“hey i’m here”); ) it’s never received the message … but if i destroy the app he receive the deconnect message … it’s normal ?
Dear rayzox,
Sorry for the error. I will check and reply. It was a perfectly working code.
Thanks.
Hi thank you. Can you find the solution ? Because i tried x) and only the sendmessage not working :/
Hi ! I test and the sendmessage not working when you use it in out of the thread (for example in a click action).
How to implement socket programming with android and php simultanaoysly……?
Hi Hussain,
Php is a server side script, if you want to call a php service you can use http calls. Or if you explicitly want a separate socket connection I suggest you to read from this documentation (http://php.net/manual/en/function.socket-create.php). Android Client part wont change other than the server IP and the PORT number.
Thanks.
How can build video call ?
Hi,
I am getting a CalledFromWrongThreadException, which causes the application to crash once I click start server. Any ideas how to fix that?
Thanks.
Dear David, Did you try copying the whole code?
Yeah, my code is exactly the same, I’ve been trying to figure it out but I can’t find a solution
I have the same issue. How was this resolved?
Can you use this with multiple clients? If not, what changes would you have to make?
socket = serverSocket.accept();
CommunicationThread commThread = new CommunicationThread(socket);
When i put debug point, it is stopping near socket = serverSocket.accept(); not going to next line. what would be the possible reason?
serverSocket.accept(); is waiting for the incoming connection, that is why debug is waiting there.
Hi code is working fine but sometimes when running this error appear and become in a endless loop
2019-05-09 09:14:35.118 9909-10009/? W/System.err: java.net.SocketException: Connection reset
2019-05-09 09:14:35.119 9909-10009/? W/System.err: at java.net.SocketInputStream.read(SocketInputStream.java:133)
2019-05-09 09:14:35.119 9909-10009/? W/System.err: at java.net.SocketInputStream.read(SocketInputStream.java:120)
2019-05-09 09:14:35.119 9909-10009/? W/System.err: at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:287)
2019-05-09 09:14:35.119 9909-10009/? W/System.err: at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:350)
2019-05-09 09:14:35.119 9909-10009/? W/System.err: at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:179)
2019-05-09 09:14:35.119 9909-10009/? W/System.err: at java.io.InputStreamReader.read(InputStreamReader.java:184)
2019-05-09 09:14:35.119 9909-10009/? W/System.err: at java.io.BufferedReader.fill(BufferedReader.java:172)
2019-05-09 09:14:35.119 9909-10009/? W/System.err: at java.io.BufferedReader.readLine(BufferedReader.java:335)
2019-05-09 09:14:35.119 9909-10009/? W/System.err: at java.io.BufferedReader.readLine(BufferedReader.java:400)
2019-05-09 09:14:35.119 9909-10009/? W/System.err: at com.test.mini.alphamaatje.Server$CommunicationThread.run(Server.java:196)
Line 196 is String read = input.readLine();
For your information I have the serverscript running as a service
Please check your internet connection or the other device i breaking the connection when you relaunch your app.
The server is running as a service on a robot device so it’s running 24 hours a day. The other device is a mobile phone. When I stop the app on the mobile phone everything goes well. But after a amount of time the server side is showing this error in logcat and is showing this in a endless loop.
This gave me always connected to the server even if the server is not running?
if (view.getId() == R.id.connect_server) {
msgList.removeAllViews();
showMessage(“Connecting to Server…”, clientTextColor);
clientThread = new ClientThread();
thread = new Thread(clientThread);
thread.start();
showMessage(“Connected to Server…”, clientTextColor);
return;
}
When i’m compiling the code it says:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.server, PID: 9736
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.example.server/com.example.server.MainActivity}: java.lang.ClassNotFoundException: Didn’t find class “com.example.server.MainActivity” on path: DexPathList[[zip file “/data/app/com.example.server-NAZlUItoBXGuoYcwlEtcqw==/base.apk”, zip file “/data/app/com.example.server-NAZlUItoBXGuoYcwlEtcqw==/split_lib_dependencies_apk.apk”, zip file “/data/app/com.example.server-NAZlUItoBXGuoYcwlEtcqw==/split_lib_resources_apk.apk”, zip file “/data/app/com.example.server-NAZlUItoBXGuoYcwlEtcqw==/split_lib_slice_0_apk.apk”, zip file “/data/app/com.example.server-NAZlUItoBXGuoYcwlEtcqw==/split_lib_slice_1_apk.apk”, zip file “/data/app/com.example.server-NAZlUItoBXGuoYcwlEtcqw==/split_lib_slice_2_apk.apk”, zip file “/data/app/com.example.server-NAZlUItoBXGuoYcwlEtcqw==/split_lib_slice_3_apk.apk”, zip file “/data/app/com.example.server-NAZlUItoBXGuoYcwlEtcqw==/split_lib_slice_4_apk.apk”, zip file “/data/app/com.example.server-NAZlUItoBXGuoYcwlEtcqw==/split_lib_slice_5_apk.apk”, zip file “/data/app/com.example.server-NAZlUItoBXGuoYcwlEtcqw==/split_lib_slice_6_apk.apk”, zip file “/data/app/com.example.server-NAZlUItoBXGuoYcwlEtcqw==/split_lib_slice_7_apk.apk”, zip file “/data/app/com.example.server-NAZlUItoBXGuoYcwlEtcqw==/split_lib_slice_8_apk.apk”, zip file “/data/app/com.example.server-NAZlUItoBXGuoYcwlEtcqw==/split_lib_slice_9_apk.apk”],nativeLibraryDirectories=[/data/app/com.example.server-NAZlUItoBXGuoYcwlEtcqw==/lib/x86, /system/lib, /system/product/lib]]
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3184)
As soon as i click on Start server button, the app crashes.
plz help me
Srijan,
Please check your package name. It’s saying Class not found.
how to getr the ip address of the server and how do i deal with IPV6 addresses . how do i depoly this on internet not local network
You need to open the port on the server you are communicating to and it will work same as in local network.
I hope you are still attending to comments on this. I have these questions. 1. Can multiple clients in different networks connect to the server?
2. How can one determine the IP address of a connected client.?
3. Do you do contract programming? If yes, your rate per hour?
Thanks.
1. Yes multiple clients can be connected to a server.
2. Yes, I think so, but not completely confident.
3. Please send a mail to coderzheaven@gmail.com.
I am trying to start the server application but I remain stuck in .jsinterface.MyActivity.
My impression is that the AndroidManifest.xml from your movie is different than the one present on repository
Hello I would like to know if it is possible to connect to his account an android game from his pc please?
Hi, does it work if I disconnect the client and then reconnect it to server again without restarting server?
It will work since you are not stopping the server.
Hey! I am working on the same principle as others.
But this code is not working on my device.
When I started the server and connecting the client with the server, it won’t connect them.
Please send me some valid code that works.
No error received.
Are your both devices on the same WiFi network?
Hey, Thanks for the tutorial! It was very helpful. I do have a problem with the start server function as when I press the button the app crashes and I get this message in the log:
E/AndroidRuntime: FATAL EXCEPTION: Thread-2
Process: com.example.servermonitor, PID: 4549
android.util.AndroidRuntimeException: Animators may only be run on Looper threads
As I am a beginner in Android programming any help would be great and probably need to be dumbed down, sorry.
You can keep the code is crashing inside a Thread.
Pingback: How to set up socket between Android App (client) and Hercules Server – Ask Android Questions
its client app cant receive message from socket server built on iOS platform. Also its server cant receive msg from ios client
What is the problem ?
Check if your port is open and if you are testing on local network, make sure to test both client and server on same network.
Hi,
I’ve just copied the same code and tried to run this. It works fine till I click on “Start Server”. Once I do that, the app closes. I tried debugging the code but couldn’t find what the problem is. Can someone help me out?
Could you please check your. Logcat log.
i need to make the code of the client full auto not clickable buttons
if you have a contact email or telegram i need some help
here is the question on the stack
https://stackoverflow.com/questions/65651196/how-to-make-a-clickable-android-java-applicaion-full-auto
what you have share source it is not able to send message to client to server and server to client it is not gettinh to anyone of them
Hello , liked your project demonstration.
Please tell Me if I can get help to an android project i’m working on about bluetooth.
I need to read data in a text view in my server (app) from a bluetooth device (bluetooth scale).
If you could guide a little I will be glad .
Thanks.
Michael
Hello, so I must be having a moment but on the Client side you set a public static final String SERVER_IP to call when running the Runnable to the server. HOW IN THE WORLD DO I SET THIS PROGRAMATICALLY? What I mean is I want to set the IP dynamically using SharedPreferences for example, then call it in the class but for some reason I get a Null pointer exception on the SharedPreferences even though I know I’ve initialized it. I know you can’t set a static final String either not sure what I’m over reading but I spent a day trying to rework your logic, changing a few things here and there & the only logic that works is if I set the IP in the code which isn’t sensible for what I’m trying to accomplish.
Thank you,
JDNA
You can get the IP from your server as a configured value if you want.
Hi Jemes,
Hope you are still replying..
I tried hard but still two android devices are not connecting to each other OVER INTERNET. I’m NOT using any WIFI and want to connect two devices using sockets.
Please help!!
You will have to open the custom port in your server to accept the incoming connections.
Pingback: [FIXED] Sockets: Android to Unity, possible allocation attack? - FixeMe
Can i connect this also with my own Server. In the Web?
yes
Pingback: Enchufes: Android para Unity, ¿posible ataque de asignación? - Unity - Unity Asset Free - Gratis
Pingback: Sockets: Android a Unity, ¿posible ataque de asignación? - android en Español