package com.openrobot.common; 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 android.os.Handler; import android.util.Log; public class ClientSocketService implements SleepyProducerConsumerInterface { private static final String TAG = "ClientService"; private String serverIpAddress; private int serverPort; private boolean connected = false; private boolean shouldWaitForServerResponse = false; private boolean currentlyWaitingForServerResponse = false; private Handler handler = new Handler(); private Socket clientSocket; private PrintWriter out; private boolean shouldTransmit = true; private ClientSocketServiceInterface delegate; private SleepyProducerConsumer sleepyProducerConsumer; private String stringToSend = null; public ClientSocketService(ClientSocketServiceInterface delegate) { super(); this.delegate = delegate; } public void disconnect() { try { // make sure to close the socket upon exiting if (clientSocket != null) { clientSocket.close(); } if (out != null) { out.flush(); out.close(); } } catch (IOException e) { e.printStackTrace(); } } public void makeConnection(String serverIp, int serverPort, boolean waitForServerResponse) { this.serverIpAddress = serverIp; this.serverPort = serverPort; this.shouldWaitForServerResponse = waitForServerResponse; Log.d(TAG, "makeConnection"); sleepyProducerConsumer = new SleepyProducerConsumer(this); if (!serverIpAddress.equals("")) { Thread cThread = new Thread(new ClientThread()); cThread.start(); } } public void closeConnection() { connected = false; } public boolean sendStringToServer(String theString) { return sleepyProducerConsumer.setProducerData(theString); } public class ClientThread implements Runnable { public void run() { try { InetAddress serverAddr = InetAddress.getByName(serverIpAddress); Log.d(TAG, "C: Connecting to: " + serverIpAddress); clientSocket = new Socket(serverAddr, serverPort); connected = true; BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream())), true); String line = null; while (connected) { if (shouldTransmit) { try { if (stringToSend != null && !currentlyWaitingForServerResponse) { // send message to Server out.println(stringToSend); Log.d(TAG, "C: Sent."); stringToSend = null; if (shouldWaitForServerResponse) { currentlyWaitingForServerResponse = true; } } else if (currentlyWaitingForServerResponse && (line = in.readLine()) != null) { delegate.clientServiceReceivedResponse(getThis(), line); currentlyWaitingForServerResponse = false; } else { Log.d(TAG, "C: Waiting on sleepyProducerConsumer."); synchronized (sleepyProducerConsumer) { sleepyProducerConsumer.wait(); } Log.d(TAG, "C: Woken up and proceeding to send data"); } } catch (Exception e) { Log.d(TAG, "S: Error", e); // connected = false; } } } clientSocket.close(); Log.d(TAG, "C: Closed."); } catch (Exception e) { Log.e(TAG, "C: Error", e); connected = false; } } } public void sleepyConsumerThreadPoppedObject(Object theObject) { if (stringToSend != null) { Log.d(TAG, "StringToSend not null, overwriting"); } stringToSend = (String) theObject; synchronized (sleepyProducerConsumer) { sleepyProducerConsumer.notify(); } } private ClientSocketService getThis() { return this; } public boolean getShouldTransmit() { return this.shouldTransmit; } public void setShouldTransmit(boolean shouldTransmit) { this.shouldTransmit = shouldTransmit; } public String getServerIpAddress() { return serverIpAddress; } public void setServerIpAddress(String serverIpAddress) { this.serverIpAddress = serverIpAddress; } public int getServerPort() { return serverPort; } public void setServerPort(int serverPort) { this.serverPort = serverPort; } public ClientSocketServiceInterface getDelegate() { return delegate; } public void setDelegate(ClientSocketServiceInterface delegate) { this.delegate = delegate; } public boolean isConnected() { return connected; } public void setConnected(boolean connected) { this.connected = connected; } }