Here is the code in Server side, Client side can be found in next post, "Simple Android Chat Application, client side"
.
MainActivity.java
package com.example.androidchatserver;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import android.support.v7.app.ActionBarActivity;
import android.widget.TextView;
import android.widget.Toast;
import android.os.Bundle;
public class MainActivity extends ActionBarActivity {
static final int SocketServerPORT = 8080;
TextView infoIp, infoPort, chatMsg;
String msgLog = "";
List<ChatClient> userList;
ServerSocket serverSocket;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
infoIp = (TextView) findViewById(R.id.infoip);
infoPort = (TextView) findViewById(R.id.infoport);
chatMsg = (TextView) findViewById(R.id.chatmsg);
infoIp.setText(getIpAddress());
userList = new ArrayList<ChatClient>();
ChatServerThread chatServerThread = new ChatServerThread();
chatServerThread.start();
}
@Override
protected void onDestroy() {
super.onDestroy();
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private class ChatServerThread extends Thread {
@Override
public void run() {
Socket socket = null;
try {
serverSocket = new ServerSocket(SocketServerPORT);
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
infoPort.setText("I'm waiting here: "
+ serverSocket.getLocalPort());
}
});
while (true) {
socket = serverSocket.accept();
ChatClient client = new ChatClient();
userList.add(client);
ConnectThread connectThread = new ConnectThread(client, socket);
connectThread.start();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
private class ConnectThread extends Thread {
Socket socket;
ChatClient connectClient;
String msgToSend = "";
ConnectThread(ChatClient client, Socket socket){
connectClient = client;
this.socket= socket;
client.socket = socket;
client.chatThread = this;
}
@Override
public void run() {
DataInputStream dataInputStream = null;
DataOutputStream dataOutputStream = null;
try {
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream = new DataOutputStream(socket.getOutputStream());
String n = dataInputStream.readUTF();
connectClient.name = n;
msgLog += connectClient.name + " connected@" +
connectClient.socket.getInetAddress() +
":" + connectClient.socket.getPort() + "\n";
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
chatMsg.setText(msgLog);
}
});
dataOutputStream.writeUTF("Welcome " + n + "\n");
dataOutputStream.flush();
broadcastMsg(n + " join our chat.\n");
while (true) {
if (dataInputStream.available() > 0) {
String newMsg = dataInputStream.readUTF();
msgLog += n + ": " + newMsg;
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
chatMsg.setText(msgLog);
}
});
broadcastMsg(n + ": " + newMsg);
}
if(!msgToSend.equals("")){
dataOutputStream.writeUTF(msgToSend);
dataOutputStream.flush();
msgToSend = "";
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (dataInputStream != null) {
try {
dataInputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (dataOutputStream != null) {
try {
dataOutputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
userList.remove(connectClient);
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this,
connectClient.name + " removed.", Toast.LENGTH_LONG).show();
msgLog += "-- " + connectClient.name + " leaved\n";
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
chatMsg.setText(msgLog);
}
});
broadcastMsg("-- " + connectClient.name + " leaved\n");
}
});
}
}
private void sendMsg(String msg){
msgToSend = msg;
}
}
private void broadcastMsg(String msg){
for(int i=0; i<userList.size(); i++){
userList.get(i).chatThread.sendMsg(msg);
msgLog += "- send to " + userList.get(i).name + "\n";
}
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
chatMsg.setText(msgLog);
}
});
}
private String getIpAddress() {
String ip = "";
try {
Enumeration<NetworkInterface> enumNetworkInterfaces = NetworkInterface
.getNetworkInterfaces();
while (enumNetworkInterfaces.hasMoreElements()) {
NetworkInterface networkInterface = enumNetworkInterfaces
.nextElement();
Enumeration<InetAddress> enumInetAddress = networkInterface
.getInetAddresses();
while (enumInetAddress.hasMoreElements()) {
InetAddress inetAddress = enumInetAddress.nextElement();
if (inetAddress.isSiteLocalAddress()) {
ip += "SiteLocalAddress: "
+ inetAddress.getHostAddress() + "\n";
}
}
}
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
ip += "Something Wrong! " + e.toString() + "\n";
}
return ip;
}
class ChatClient {
String name;
Socket socket;
ConnectThread chatThread;
}
}
/res/layout/activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Char Server"
android:textStyle="bold" />
<TextView
android:id="@+id/infoport"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="italic" />
<TextView
android:id="@+id/infoip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="italic" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="@+id/chatmsg"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</ScrollView>
</LinearLayout>
make sure Add uses-permission of "android.permission.INTERNET" to AndroidManifest.xml.
Download the files.
Related:
- Command line version Chat Server.
Next:
- Android Chat example, with server sending individual message to specify client.
Added@2014-12-06
If you found "Something Wrong! java.net.SocketException" displayed.
Make sure add permission of "android.permission.INTERNET" in AndroidManifest.xml. It's a common error of missing "android.permission.INTERNET" to cause SocketException.
Simply awesome!!! :) Just awesome... Thank you so much for this mind blowing tutorial...!
ReplyDeletewhen I try to run this an error occurs saying "ActionBarActivity cannot be resolved to a type"
ReplyDeleteany idea why that is?
hello senurz,
ReplyDeleteIs it your case? "The import android.support.v7 cannot be resolved" and "ActionBarActivity cannot be resolved to a type"
Adding 'android-support-v7-appcompat' support library to the project did the trick!
ReplyDeleteThank you Andr.oid Eric!
Hello Kissy Mae Padayjag,
ReplyDeleteAre you miss "android.permission.INTERNET" in AndroidManifest.xml?
Please check the post updated with video.
Nice tutorial!!
ReplyDeleteI am facing error in styles.xml(in res
->values folder).. just downloaded the source code from your site
kindly reply urgent!!
It's like getting the water in the sand. Feeling great after 2 days of R & D on Socket Programming i got the right working solution
ReplyDeleteThanks for the example. I found out that readUTF uses a modified UTF-16 encoding. The size of buffer your sending needs be the first byte of what your sending. Something like '123' would actually translate to { 0, 3, 0, 49, 0, 50, 0, 51 } in raw bytes ... I hope that saves someone a headache when writing a client in a different language.
ReplyDeletesir i cannot download the attachments so i copy pasted the code and updated the manifest and copy pasted a android-support-v7-appcompat.jar to project but it stops on start saying NoClassDefFound
ReplyDeleteHi.i am developing an app in which i used your code for Server/Client connections...my app is getting crashed when i try to run it...in log cat the error shown was related to when i try to add Chat-Client to
ReplyDeleteuserList.when i use this List in my code it throws null pointer exception...please help me solve this issue
i use eclipse target 17 and i run this application on 2 emulator android on eclipse but i have an exception connection refused,plz help me
ReplyDeleteevery time i click connect i get
ReplyDeletejava.net.ConnectException failed to connect to /192.168.1.21 port(8080): connect failed: ECONNREFUSED (Connection refused)
i have added the internet permission to the manifest but i don't know what the problem is. can anyone help?
same question fm my side :
ReplyDelete"every time i click connect i get
java.net.ConnectException failed to connect to /192.168.1.21 port(8080): connect failed: ECONNREFUSED (Connection refused)
i have added the internet permission to the manifest but i don't know what the problem is. can anyone help?
"
after getting connection refused errors i tried this: i shared my phone's internet (mobile data) with my tablet and then tried to connect again and this time it worked! i tried different ports and it works very well. it seems that there is a problem with my router or something that does not let me establish a connection. i hope this works for others like me.
ReplyDeleteI am not sure but I think when client disconnect from the application, Toast that writes "removed" does not seem immediately.It is seen after a new client connects and sends a message.How can i handle this? Thanks for the answers.
ReplyDeletedoes this use GCM?
ReplyDeleteshowing error java.net.SocketException:socket failed:EACCES(permission denied)....
ReplyDeletemake sure Add uses-permission of "android.permission.INTERNET" to AndroidManifest.xml.
ReplyDeletehello sir how we can share image over the group and it is possible to make one to one chating as well as make chating over the different network.
ReplyDeleteThanks alot . its best and simplest .....
ReplyDeleteI'm getting this error.
ReplyDeleteFailed to set EGL_SWAP_BEHAVIOR on surface 0x977f91a0, error=EGL_BAD_MATCH
Skipped 71 frames! The application may be doing too much work on its main thread
Sir, I'm using your code in our thesis study it Good, but i want to know if the server can interact also to the client.Thanks.
ReplyDeleteIs this app requires WIFI/Internet? Please respond.
ReplyDeleteThanks
Both client and server have to be inside the same WiFi network.
ReplyDeleteThank you Eric for sharing this application.
ReplyDeleteI've faced just one problem in this that the ip of the server keeps changing. Can you please tell me if u know a way to handle this frequent ip changing problem.
I need to, server send real time video from camera instead of text to client. do you know how?
ReplyDeleteI am using esp8266 wifi module.Both the mobile which runs ChatServer and esp8266 are connected to same wifi. After configuring esp8266 module with ip address and port number displayed in ChatServer application, connection is established and data is also sent from esp8266 but it is not displayed on the mobile ChatServer application. Why ? Does this ChatServer application only work on ChatClient application from another mobile and not from any other devices or terminal from pc ?
ReplyDelete