Pages

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

Related Posts by Categories

0 comments:

Post a Comment