Pages

Showing posts with label server. Show all posts
Showing posts with label server. Show all posts

Thursday, May 5, 2016

Android Chat example with server sending individual message to specify client


Refer to my old post of Simple Android Chat Application, server side, and client side. Function to send sending individual message to specify client is added in server side.


uses-permission of "android.permission.INTERNET" is needed in AndroidManifest.xml, for both server and client.


Server side:

MainActivity.java
package com.blogspot.android_er.androidchatserver;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

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;

public class MainActivity extends AppCompatActivity {

static final int SocketServerPORT = 8080;

TextView infoIp, infoPort, chatMsg;
Spinner spUsers;
ArrayAdapter<ChatClient> spUsersAdapter;
Button btnSentTo;

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

spUsers = (Spinner) findViewById(R.id.spusers);
userList = new ArrayList<ChatClient>();
spUsersAdapter = new ArrayAdapter<ChatClient>(
MainActivity.this, android.R.layout.simple_spinner_item, userList);
spUsersAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spUsers.setAdapter(spUsersAdapter);

btnSentTo = (Button)findViewById(R.id.sentto);
btnSentTo.setOnClickListener(btnSentToOnClickListener);

infoIp.setText(getIpAddress());

ChatServerThread chatServerThread = new ChatServerThread();
chatServerThread.start();
}

View.OnClickListener btnSentToOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
ChatClient client = (ChatClient)spUsers.getSelectedItem();
if(client != null){
String dummyMsg = "Dummy message from server. ";
client.chatThread.sendMsg(dummyMsg);
msgLog += "- Dummy message to " + client.name + " ";
chatMsg.setText(msgLog);

}else{
Toast.makeText(MainActivity.this, "No user connected", Toast.LENGTH_LONG).show();
}
}
};

@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("Im waiting here: "
+ serverSocket.getLocalPort());
}
});

while (true) {
socket = serverSocket.accept();
ChatClient client = new ChatClient();
userList.add(client);
ConnectThread connectThread = new ConnectThread(client, socket);
connectThread.start();

runOnUiThread(new Runnable() {
@Override
public void run() {
spUsersAdapter.notifyDataSetChanged();
}
});
}

} 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() + " ";
MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
chatMsg.setText(msgLog);
}
});

dataOutputStream.writeUTF("Welcome " + n + " ");
dataOutputStream.flush();

broadcastMsg(n + " join our chat. ");

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() {
spUsersAdapter.notifyDataSetChanged();
Toast.makeText(MainActivity.this,
connectClient.name + " removed.", Toast.LENGTH_LONG).show();

msgLog += "-- " + connectClient.name + " leaved ";
MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
chatMsg.setText(msgLog);
}
});

broadcastMsg("-- " + connectClient.name + " leaved ");
}
});
}

}

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 + " ";
}

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() + " ";
}

}

}

} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
ip += "Something Wrong! " + e.toString() + " ";
}

return ip;
}

class ChatClient {
String name;
Socket socket;
ConnectThread chatThread;

@Override
public String toString() {
return name + ": " + socket.getInetAddress().getHostAddress();
}
}
}


activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout

android_layout_width="match_parent"
android_layout_height="match_parent"
android_padding="16dp"
android_orientation="vertical"
tools_context="com.blogspot.android_er.androidchatserver.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" />

<Spinner
android_id="@+id/spusers"
android_layout_width="match_parent"
android_layout_height="wrap_content"/>

<Button
android_id="@+id/sentto"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_text="Sent msg to individual user"/>

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



download filesDownload the server side files (Android Studio Format) .

Client side same as in the post "Simple Android Chat Application, client side" in Android Studio form.

download filesDownload the client side files (Android Studio Format) .

Read More..

Wednesday, February 17, 2016

Simple HTTP server running on Android

Its my old exercise "Implement simple HTTP server running on Android". Somebody report its not work, so I re-try it on Android Studio. Actually the code is same as before, and work as expected. Please notice both the server and client have to connect in the same WiFi network.


Updated@2015-11-26:
This code NOT work on Android 5, may be all 5+ version.
Fixed, refer next post "socket.getInetAddress() return null on Android 5".


Work on Xiaomi Redmi 2, running Android 4.4.4


MainActivity.java
package com.blogspot.android_er.androidhttpserver;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.EditText;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Enumeration;

public class MainActivity extends AppCompatActivity {

EditText welcomeMsg;
TextView infoIp;
TextView infoMsg;
String msgLog = "";

ServerSocket httpServerSocket;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

welcomeMsg = (EditText) findViewById(R.id.welcomemsg);
infoIp = (TextView) findViewById(R.id.infoip);
infoMsg = (TextView) findViewById(R.id.msg);

infoIp.setText(getIpAddress() + ":"
+ HttpServerThread.HttpServerPORT + " ");

HttpServerThread httpServerThread = new HttpServerThread();
httpServerThread.start();
}

@Override
protected void onDestroy() {
super.onDestroy();

if (httpServerSocket != null) {
try {
httpServerSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

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() + " ";
}

}

}

} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
ip += "Something Wrong! " + e.toString() + " ";
}

return ip;
}

private class HttpServerThread extends Thread {

static final int HttpServerPORT = 8888;

@Override
public void run() {
Socket socket = null;

try {
httpServerSocket = new ServerSocket(HttpServerPORT);

while(true){
socket = httpServerSocket.accept();

HttpResponseThread httpResponseThread =
new HttpResponseThread(
socket,
welcomeMsg.getText().toString());
httpResponseThread.start();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}

private class HttpResponseThread extends Thread {

Socket socket;
String h1;

HttpResponseThread(Socket socket, String msg){
this.socket = socket;
h1 = msg;
}

@Override
public void run() {
BufferedReader is;
PrintWriter os;
String request;

try {
is = new BufferedReader(new InputStreamReader(socket.getInputStream()));
request = is.readLine();

os = new PrintWriter(socket.getOutputStream(), true);

String response =
"<html><head></head>" +
"<body>" +
"<h1>" + h1 + "</h1>" +
"</body></html>";

os.print("HTTP/1.0 200" + " ");
os.print("Content type: text/html" + " ");
os.print("Content length: " + response.length() + " ");
os.print(" ");
os.print(response + " ");
os.flush();
socket.close();

msgLog += "Request of " + request
+ " from " + socket.getInetAddress().toString() + " ";
MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {

infoMsg.setText(msgLog);
}
});

} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

return;
}
}
}


layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout


android_layout_width="match_parent"
android_layout_height="match_parent"
android_padding="16dp"
android_orientation="vertical"
tools_context="com.blogspot.android_er.androidhttpserver.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" />

<EditText
android_id="@+id/welcomemsg"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_text="Welcome from Android-er" />

<TextView
android_id="@+id/infoip"
android_layout_width="wrap_content"
android_layout_height="wrap_content" />

<ScrollView
android_layout_width="match_parent"
android_layout_height="match_parent" >

<TextView
android_id="@+id/msg"
android_layout_width="wrap_content"
android_layout_height="wrap_content" />
</ScrollView>
</LinearLayout>


Permission of "android.permission.INTERNET" is needed in AndroidManifest.xml.

download filesDownload the files (Android Studio Format) .
Read More..