I have an android app. I want to send a string to java server when I touch the button each time in my client app.I am able to connect to server.
But the problem is when I touch the button, no string is sending to server. No matter how many times I touch the button the string is not sending but suddenly when I exit the app in my smartphone, means when I destroy the activity, all the strings then transfers to the server at the same time.
If I touch the button 100 times, 100 same strings are transferred to the server only when I destroy activity. I want the string to be transferred to server at the time when I touch the button.
Please help me with this. I am a newbie. My code is below:
public class Joystick extends Activity {
BluetoothAdapter ba=BluetoothAdapter.getDefaultAdapter();
//local bluetooth adapter object created
BluetoothDevice bd; //GLOBAL DECLARATION BLOCK
BluetoothSocket bs;
OutputStream os;
InputStream in;
Button up;
private static final UUID MY_UUID =UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.joystick);
up= (Button) findViewById(R.id.up);
if(ba.isEnabled()==false) //BLUETOOTH ADAPTER ENABLED IF WAS DISABLED
ba.enable();
final String address = getIntent().getStringExtra("address").trim();
setResult(100, new Intent());
bd=ba.getRemoteDevice(address);
BluetoothConnect.start();
}
#Override
protected void onResume(){
super.onResume();
up.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
try {
os = bs.getOutputStream();
String message = "up";
byte[] msgBuffer = message.getBytes();
os.write(msgBuffer);
} catch (IOException e) {
e.printStackTrace();
}
break;
case MotionEvent.ACTION_UP:
try {
os.flush();
} catch (IOException e) {
e.printStackTrace();
}
break;
}
return true;
}
});
}
Thread BluetoothConnect = new Thread(){
public void run(){
try {
bs=bd.createRfcommSocketToServiceRecord(MY_UUID);
bs.connect();
} catch (IOException e) {
try {
bs.close();
} catch (IOException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}
}
};
protected void onStop(){
super.onStop();
try {
os.close();
bs.close();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
protected void onPause() {
super.onPause();
if (os != null) {
try {
os.flush();
} catch (IOException e) {
}
}
}}
the server code is:
public class SimpleSPPServer {
private static Robot robot;
//start server
private void startServer() throws IOException{
//Create a UUID for SPP
UUID uuid = new UUID("1101", true);
//Create the servicve url
String connectionString = "btspp://localhost:" + uuid +";name=SampleSPPServer";
//open server url
StreamConnectionNotifier streamConnNotifier = (StreamConnectionNotifier)Connector.open( connectionString );
//Wait for client connection
System.out.println("\nServer Started. Waiting for clients to connect...");
StreamConnection connection=streamConnNotifier.acceptAndOpen();
RemoteDevice dev = RemoteDevice.getRemoteDevice(connection);
System.out.println("Remote device address: "+dev.getBluetoothAddress());
System.out.println("Remote device name: "+dev.getFriendlyName(true));
//read string from spp client
InputStream inStream=connection.openInputStream();
BufferedReader bReader=new BufferedReader(new InputStreamReader(inStream));
String lineRead=bReader.readLine();
System.out.println(lineRead);
try{
robot=new Robot();
if(lineRead.equalsIgnoreCase("up")){
robot.keyPress(KeyEvent.VK_UP);
robot.keyRelease(KeyEvent.VK_UP);
} }
catch(AWTException e){
System.out.println("exception while creating robot instance");
}
//send response to spp client
OutputStream outStream=connection.openOutputStream();
PrintWriter pWriter=new PrintWriter(new OutputStreamWriter(outStream));
pWriter.write("Response String from SPP Server\r\n");
pWriter.flush();
pWriter.close();
streamConnNotifier.close();
}
public static void main(String[] args) throws IOException {
//display local device address and name
LocalDevice localDevice = LocalDevice.getLocalDevice();
System.out.println("Address: "+localDevice.getBluetoothAddress());
System.out.println("Name: "+localDevice.getFriendlyName());
SimpleSPPServer sampleSPPServer=new SimpleSPPServer();
sampleSPPServer.startServer();
}
}
Problem solved.. Just add "\n" at the end of string you want to transfer.
Related
This question already has answers here:
What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?
(26 answers)
Closed 3 years ago.
I am want to separate the strings incoming from arduino and store it in variables for database purposes but when I try to divide that string using split() after a few moments the exception occurs
java.lang.ArrayIndexOutOfBoundsException: length=1; index=1 and the app keeps stopping
the error is at Line 203 separated[1]
public class MainActivity extends AppCompatActivity {
private static final String TAG = "Android-Arduino";
Button btnOn, btnOff;
TextView temperatureText, heartbeatText;
Handler h;
final int RECIEVE_MESSAGE = 1;
private BluetoothAdapter btAdapter = null;
private BluetoothSocket btSocket = null;
private StringBuilder sb = new StringBuilder();
private ConnectedThread connectedThread;
// Common service that bluetooth device support
private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
// MAC address of the bluetooth module.
private static String address = "00:18:E4:35:75:A6";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
temperatureText = (TextView) findViewById(R.id.temp);
heartbeatText = (TextView)findViewById(R.id.heartbeat);
getDataArduino();
// Bluetooth adapter
btAdapter = BluetoothAdapter.getDefaultAdapter();
// Check whether the bluetooth is enabled / disabled
checkBTState();
}
// Creates the communication chanel
private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOException {
if(Build.VERSION.SDK_INT >= 10){
try {
final Method m = device.getClass().
getMethod("createInsecureRfcommSocketToServiceRecord", new Class[]{UUID.class });
return (BluetoothSocket) m.invoke(device, MY_UUID);
} catch (Exception e) {
Log.e(TAG, "Could not create Insecure RFComm Connection",e);
}
}
return device.createRfcommSocketToServiceRecord(MY_UUID);
}
#Override
public void onResume() {
super.onResume();
// Set up a pointer to the remote node using it's address.
BluetoothDevice device = btAdapter.getRemoteDevice(address);
try {
btSocket = createBluetoothSocket(device);
} catch (IOException e) {
errorExit("Fatal Error", "In onResume() and socket create failed: "
+ e.getMessage() + ".");
}
btAdapter.cancelDiscovery();
try {
btSocket.connect();
} catch (IOException e) {
try {
btSocket.close();
} catch (IOException ex) {
errorExit("Fatal Error", "In onResume() and unable to close socket during " +
"connection failure" + ex.getMessage() + ".");
}
}
// Creates the data stream with the server
connectedThread = new ConnectedThread(btSocket);
connectedThread.start();
}
#Override
public void onPause() {
super.onPause();
try {
btSocket.close();
} catch (IOException ex) {
errorExit("Fatal Error", "In onPause() and failed to close socket." +
ex.getMessage() + ".");
}
}
private void checkBTState() {
// Checks if the devices has bluetooth functionalities
if(btAdapter==null) {
errorExit("Fatal Error", "Bluetooth not support");
} else {
// Checks if the bluetooth is on
if (btAdapter.isEnabled()) {
} else {
// Prompt user to turn on Bluetooth
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, 1);
}
}
}
private void errorExit(String title, String message){
Toast.makeText(getBaseContext(), title + " - " + message, Toast.LENGTH_LONG).show();
finish();
}
private class ConnectedThread extends Thread {
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[256]; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
// Read from the InputStream
// Get number of bytes and message in "buffer"
bytes = mmInStream.read(buffer);
// Send to message queue Handler
h.obtainMessage(RECIEVE_MESSAGE, bytes, -1, buffer).sendToTarget();
} catch (IOException e) {
break;
}
}
}
//Call this from the main activity to send data to the remote device
public void write(String message) {
byte[] msgBuffer = message.getBytes();
try {
mmOutStream.write(msgBuffer);
} catch (IOException e) {
Log.d(TAG, "...Error data send: " + e.getMessage() + "...");
}
}
}
public void getDataArduino() {
temperatureText.clearComposingText();
h = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case RECIEVE_MESSAGE:
byte[] readBuf = (byte[]) msg.obj;
String strIncom = new String(readBuf, 0, msg.arg1);
sb.append(strIncom);
int endOfLineIndex = sb.indexOf("\n");
if (endOfLineIndex > 0) {
String sbprint = sb.substring(0, endOfLineIndex);
sb.delete(0, sb.length());
String[] separated = sbprint.split(":");
heartbeatText.setText(separated[0]+ "");
temperatureText.setText(separated[1]+ "");
}
Log.d(TAG, "...String:"+ sb.toString() + "Byte:" + msg.arg1 + "...");
break;
}
}
};
}
}
I need the temperature to display differently and heartrate to be displayed individually.
You can first try to print the input data (StringBuffer sb) and split String array(String[] separated). You are getting error because the Strings have not split as your expected and only 1 element is present in the array sbprint, this is why when you try to access the second element you get ArrayIndexOutofBound index.
Once you print the Split String Array it would give you an idea where your data is wrong.
So I am trying to connect to a device that is going to acquire analogue data(Red Pitaya). It has set scpi commands that control the device. I can control these through labview and using putty.
I am trying to write and android application that can access the devices scpi server and send commands to it for the device to complete.
The device is programmed in a way in that you first have to connect to the server using a SSH connection which i have no problem doing using JSch, from there you can send a command to start the scpi server and open a connection.
Now this is the bit i am struggling with and i dont understand why, when the SCPI server has started it is accessed through the Ip of the device and a raw port of 5000, but i cannot seem to write a piece of code that connects to this and performs a SCPI command. I am not to sure whether it is the connection or the way i have sent the data.
This is the code
public class rp_command extends AsyncTask<Void,Void, Void> {
String ipAddress;
int port;
String response = "";
TextView textResponse;
rp_command(String address, int rp_port, TextView textResponse){
ipAddress = address;
port = rp_port;
this.textResponse = textResponse;
}
#Override
protected Void doInBackground(Void...arg0){
Socket socket = null;
try{
socket = new Socket(ipAddress, port);
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
out.writeByte(1);
out.writeUTF("DIG:PIN LED2,1");
out.flush();
} catch (UnknownHostException e){
e.printStackTrace();
response = "UnknownHostException:" + e.toString();
} catch (IOException e){
e.printStackTrace();
response = "IOException:" + e.toString();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}return null;
}
#Override
protected void onPostExecute(Void result){
textResponse.setText(response);
super.onPostExecute(result);
}
}
If anyone has any advice it would be appreciated
thanks
Got it working here i believe the issue was due to not ending a command with \r\n being at the end of the string here is the working test code if anyone is interested. This is for sending a string not receiving.
public class MainActivity extends AppCompatActivity {
Socket s = new Socket();
PrintWriter s_out;
BufferedReader s_in;
String out = null;
public void sendCommand (String command){
try {
s_out = new PrintWriter(s.getOutputStream(), true);
s_out.println(command);
}catch (IOException e){
System.out.println(e);
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button LED_ON, LED_OFF;
LED_ON = (Button)findViewById(R.id.button);
LED_OFF = (Button)findViewById(R.id.button2);
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
try{
s.connect(new InetSocketAddress("192.168.0.104", 5000));
}catch (IOException e){
System.out.println(e);
}
LED_ON.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
sendCommand("DIG:PIN LED2,1\r\n");
}
});
LED_OFF.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
sendCommand("DIG:PIN LED2,0\r\n");
}
});
}
}
When using buttons to initiate a command i noticed that if you write the send command code in there instead of a separate function the app would time out and crash.
I use socket.io-client-java library
I have android client and Java server
Server code:
public class Server {
public static void main(String[] args) throws IOException {
System.out.println("Welcome to Server side");
BufferedReader in = null;
PrintWriter out = null;
ServerSocket servers = null;
Socket fromclient = null;
// create server socket
try {
servers = new ServerSocket(4444);
} catch (IOException e) {
System.out.println("Couldn't listen to port 4444");
System.exit(-1);
}
try {
System.out.print("Waiting for a client...");
fromclient = servers.accept();
System.out.println("Client connected");
} catch (IOException e) {
System.out.println("Can't accept");
System.exit(-1);
}
in = new BufferedReader(new
InputStreamReader(fromclient.getInputStream()));
out = new PrintWriter(fromclient.getOutputStream(), true);
String input, output;
System.out.println("Wait for messages");
while ((input = in.readLine()) != null) {
if (input.equalsIgnoreCase("exit")) break;
out.println("S ::: " + input);
System.out.println(input);
}
out.close();
in.close();
fromclient.close();
servers.close();
}
}
And client:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Socket mSocket = null;
private Button button;
{
try {
mSocket = IO.socket(Constants.CHAT_SERVER_URL);
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
button.setOnClickListener(this);
mSocket.connect();
}
#Override
public void onClick(View v) {
if (v.getId() == R.id.button){
mSocket.emit("new message", "Some message");
}
}
}
And if I tried connect to server I get this:
Welcome to Server side
Waiting for a client...Client connected
Wait for messages
GET /socket.io/?EIO=3&transport=polling HTTP/1.1
User-Agent: Dalvik/1.4.0 (Linux; U; Android 2.3.7; Android SDK built for x86 Build/GINGERBREAD)
Host: 10.0.2.2:4444
Connection: Keep-Alive
Accept-Encoding: gzip
But when I tried to send String message
mSocket.emit("new message", "Some message");
Nothing happens. I send the wrong or server is wrong?
To properly init socket.io client, you need to do something like this:
Socket _socket = IO.socket(SERVER_URI);
_socket.on(Socket.EVENT_CONNECT, _onConnectionListener)
.on(Socket.EVENT_DISCONNECT, _onDisconnectListener)
.on(Socket.EVENT_CONNECT_ERROR, _onConnectionErrorListener)
.on(Socket.EVENT_MESSAGE, _onMessageReceivedListener)
.on(CHAT_MESSAGE_PUBLISH, _onMessageReceivedListener);
Each of listeners is run when the event takes place, e.g.:
private Emitter.Listener _onMessageReceivedListener = new Emitter.Listener() {
#Override
public void call(Object... args) {
JSONArray jsonArray = (JSONArray) args[0];
if (jsonArray != null && jsonArray.length() > 0) {
Gson gson = new Gson();
List<MessageModel> historyList = gson.fromJson(jsonArray.toString(), listType);
loadReceivedMessage(historyList);
chatLoging(jsonArray.toString());
}
}
};
The call() method will be triggered when you a receive new message from the server.
I'm currently working on an android chat application.
First, I have created the server and then, the android client. But for some reason, the client cannot connect to the server. Nevertheless, I have specified the same port for both client and server.
Could you help me, please ?
Here is the code of my server :
public class ChatServer {
private static int port = 8080;
public static void main (String[] args) throws IOException {
ServerSocket server = new ServerSocket(port); /* start listening on the port */
System.out.println( "Listening on "+ server );
Socket client = null;
while(true) {
try {
client = server.accept();
System.out.println( "Connection from " + client );
/* start a new thread to handle this client */
Thread t = new Thread(new ClientConnect(client));
t.start();
} catch (IOException e) {
System.err.println("Accept failed.");
System.err.println(e);
System.exit(1);
server.close();
}
}
}
}
and here is the client :
public class MainActivity extends Activity implements OnClickListener{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EditText nickname = (EditText)findViewById(R.id.nicknameField);
EditText password = (EditText)findViewById(R.id.passwordField);
Button signin = (Button) findViewById(R.id.signin);
Button signup = (Button) findViewById(R.id.signup);
new Downloader(this).execute(8080);
}
and the Asynctask class
public class Downloader extends AsyncTask<Integer, Void, Void> {
private WeakReference<MainActivity> activity;
private int port;
public Downloader(MainActivity act){
super();
activity = new WeakReference<MainActivity>(act);
}
protected Void doInBackground(Integer... params) {
port = params[0];
try {
Socket clientSocket = new Socket("localhost", port);
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
When I used the debugger on eclipse, it goes through the line
Socket clientSocket = new Socket("localhost", port);
but after that it goes to the IOException.
Thanks for your help !
You can go to the properties of Android on the emulator equal like you do on a smartphone Android and see the ip you go atributed.
But if you still using the Eclipse i advise you to change to Android Studio but i think you gonna have a problema with SDK you have to unnistall that but beside that no problems.
I made a simple prototype of a client-server application on Android
I managed to connect two clients to the server and the server can receive their messages. The problem now is that I can't seem to broadcast/receive the messages to other clients.
I try to broadcast the received message through a for loop in the Server class:
private void broadcastMessage(String message) {
for (int i = 0, j = clients.size(); i <= j; i++) {
PrintWriter out = null;
Socket socket = clients.get(i);
try {
out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())), true);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// WHERE YOU ISSUE THE COMMANDS
out.println(message);
Log.d("SERVER Loop", "Broadcasting messages...");
out.close();
}
Log.d("SERVER", "Message Brodcasted");
}
This I then try to receive through a listener in the Client class :
public class ClientThreadListener implements Runnable {
protected Socket serverSocket = null;
protected String mMsgFromServer;
public ClientThreadListener(Socket serverSocket) {
this.serverSocket = serverSocket;
}
public void run() {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(
serverSocket.getInputStream()));
while ((mMsgFromServer = in.readLine()) != null) {
Log.d("MESSAGE FROM SERVER: ", mMsgFromServer);
handler.post(new Runnable() {
#Override
public void run() {
msgFromOtherClients.append('\n'
+ "Message From Server: " + mMsgFromServer);
}
});
}
} catch (Exception e) {
Log.e("ClientListener", "C: Error", e);
connected = false;
}
}
}
I don't get any errors or force closes though. Forgive me I know it is very messy but please bear with me and please focus on the issue at hand instead :D
Here is the full code for the Server class
public class Server extends Activity {
private TextView serverStatus;
// DEFAULT IP
public static String SERVERIP = "10.0.2.15";
// DESIGNATE A PORT
public static final int SERVERPORT = 8080;
private Handler handler = new Handler();
private ServerSocket serverSocket;
private String mMsgFromClient;
private MultiThreadedServer server;
private ArrayList<Socket> clients = new ArrayList<Socket>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.server);
serverStatus = (TextView) findViewById(R.id.server_status);
// SERVERIP = getLocalIpAddress();
server = new MultiThreadedServer(8080);
new Thread(server).start();
}
public class MultiThreadedServer implements Runnable {
protected int serverPort = 8080;
protected ServerSocket serverSocket = null;
protected boolean isStopped = false;
protected Thread runningThread = null;
public MultiThreadedServer(int port) {
this.serverPort = port;
}
public void run() {
synchronized (this) {
this.runningThread = Thread.currentThread();
}
openServerSocket();
while (!isStopped()) {
Socket clientSocket = null;
try {
clientSocket = this.serverSocket.accept();
clients.add(clientSocket);
} catch (IOException e) {
if (isStopped()) {
Log.d("SERVER TEXT", "Server Stopped.");
return;
}
throw new RuntimeException(
"Error accepting client connection", e);
}
new Thread(new WorkerRunnable(clientSocket, this)).start();
}
Log.d("SERVER TEXT", "Server Stopped.");
}
private synchronized boolean isStopped() {
return this.isStopped;
}
public synchronized void stop() {
this.isStopped = true;
try {
this.serverSocket.close();
} catch (IOException e) {
throw new RuntimeException("Error closing server", e);
}
}
private void openServerSocket() {
try {
this.serverSocket = new ServerSocket(this.serverPort);
} catch (IOException e) {
throw new RuntimeException("Cannot open port 8080", e);
}
}
private void broadcastMessage(String message) {
for (int i = 0, j = clients.size(); i <= j; i++) {
PrintWriter out = null;
Socket socket = clients.get(i);
try {
out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())), true);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// WHERE YOU ISSUE THE COMMANDS
out.println(message);
Log.d("SERVER Loop", "Broadcasting messages...");
out.close();
}
Log.d("SERVER", "Message Brodcasted");
}
}
public class WorkerRunnable implements Runnable {
protected Socket clientSocket = null;
protected String mMsgFromClient = null;
private UUID id;
public WorkerRunnable(Socket clientSocket, MultiThreadedServer server) {
this.clientSocket = clientSocket;
id = UUID.randomUUID();
}
public void run() {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
while ((mMsgFromClient = in.readLine()) != null) {
handler.post(new Runnable() {
#Override
public void run() {
serverStatus.append('\n'
+ "Message From Client ID " + getID()
+ ": " + mMsgFromClient);
}
});
}
Log.d("SERVERTEXT", "Proceed to broadcast");
server.broadcastMessage(mMsgFromClient);
} catch (IOException e) {
Handler handler = new Handler();
handler.post(new Runnable() {
#Override
public void run() {
serverStatus
.append('\n'
+ "Message From Client ID "
+ getID()
+ ": "
+ "Oops. Connection interrupted. Please reconnect your phones.");
}
});
e.printStackTrace();
}
}
private String getID() {
return id.toString();
}
}
}
Here is the full code for the Client class
public class Client extends Activity {
private EditText serverIp;
private EditText chatMsg;
private Button connectPhones;
private Button sendMsg;
private TextView msgFromOtherClients;
private String serverIpAddress = "";
private boolean connected = false;
private boolean willSendMsg = false;
private Handler handler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.client);
serverIp = (EditText) findViewById(R.id.server_ip);
connectPhones = (Button) findViewById(R.id.connect_phones);
connectPhones.setOnClickListener(connectListener);
chatMsg = (EditText) findViewById(R.id.chat_msg);
sendMsg = (Button) findViewById(R.id.send_msg);
sendMsg.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
willSendMsg = true;
}
});
msgFromOtherClients = (TextView) findViewById(R.id.msg_from_other_clients);
}
private OnClickListener connectListener = new OnClickListener() {
#Override
public void onClick(View v) {
if (!connected) {
serverIpAddress = serverIp.getText().toString();
if (!serverIpAddress.equals("")) {
Thread cThread = new Thread(new ClientThread());
cThread.start();
}
}
}
};
public class ClientThread implements Runnable {
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName(serverIpAddress);
Log.d("ClientActivity", "C: Connecting...");
Socket socket = new Socket(serverAddr, Server.SERVERPORT);
connected = true;
Thread listener = new Thread(new ClientThreadListener(new Socket(serverAddr, Server.SERVERPORT)));
listener.start();
while (connected) {
if (willSendMsg) {
willSendMsg = false;
try {
Log.d("ClientActivity", "C: Sending command.");
PrintWriter out = new PrintWriter(
new BufferedWriter(new OutputStreamWriter(
socket.getOutputStream())), true);
// WHERE YOU ISSUE THE COMMANDS
out.println(chatMsg.getText().toString());
Log.d("ClientActivity", "C: Sent.");
} catch (Exception e) {
Log.e("ClientActivity", "S: Error", e);
}
}
}
socket.close();
Log.d("ClientActivity", "C: Closed.");
} catch (Exception e) {
Log.e("ClientActivity", "C: Error", e);
connected = false;
}
}
}
public class ClientThreadListener implements Runnable {
protected Socket serverSocket = null;
protected String mMsgFromServer;
public ClientThreadListener(Socket serverSocket) {
this.serverSocket = serverSocket;
}
public void run() {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(
serverSocket.getInputStream()));
while ((mMsgFromServer = in.readLine()) != null) {
Log.d("MESSAGE FROM SERVER: ", mMsgFromServer);
handler.post(new Runnable() {
#Override
public void run() {
msgFromOtherClients.append('\n'
+ "Message From Server: " + mMsgFromServer);
}
});
}
} catch (Exception e) {
Log.e("ClientListener", "C: Error", e);
connected = false;
}
}
}
}
Your code has some issue that prevents it from working.
As already said in other answers, in your code you are closing the socket output stream right after sending the message to the client. call close() only out of your for message loop. Of course closing the socket in the client will have the same effect as closing it on the server. You must close the sockets only when client and server have finished talking. Closing it while transmitting data it's like hanging up the phone in the middle of a conversation.
Second, you create a new socket on the client side:
Log.d("ClientActivity", "C: Connecting...");
Socket socket = new Socket(serverAddr, Server.SERVERPORT);
but then you pass to the listener another, newly created, socket (I suppose this is not intended):
connected = true;
Thread listener = new Thread(new ClientThreadListener(new Socket(serverAddr, Server.SERVERPORT)));
listener.start();
Third, always call flush() on an output stream right after sending data, or the data will likely not be sent (the send methods will just enqueue your data in the sending buffer).
Last (This may not be useful to you since I don't know your ultimate goal), if you need to send and receive on sockets, 90% of the time it's better and easier to do this asinchronously, using separate threads for listening and sending.
If it still doesn't work, add here some output or log trace from logcat.
You need to move the line:
server.broadcastMessage(mMsgFromClient);
inside the while:
while ((mMsgFromClient = in.readLine()) != null) {
handler.post(new Runnable() {
#Override
public void run() {
serverStatus.append('\n'
+ "Message From Client ID " + getID()
+ ": " + mMsgFromClient);
}
});
// HERE
Log.d("SERVERTEXT", "Proceed to broadcast");
server.broadcastMessage(mMsgFromClient);
}
Otherwise, you'll only broadcast null.
EDIT: You should make sure that mMsgFromClient is not changed between posting the new Runnable and it actually executing. The best way is to initialize a field in the anonymous class with the current value, and log the value of that field instead.
EDIT2: Unless your server is supposed to close its connection to a client after sending it a broadcast message, you should use out.flush() instead of out.close() in the broadcastMessage method. It's preferrable that client connections are closed after a timeout, or just let the clients disconnect, again with a timeout.
Otherwise, your test will be very limited most of the times: a client connects and sends a message; then it receives its own message and the server closes the connection.
Please try to use AsyncTask in android which will create separate thread for communication with server.