// Android requires network operations to be handled on a separate thread to // prevent blocking the main thread. This class sets up a separate send thread to // handle outgoing messages. public class WebsocketWrapper implements Runnable{ private final Queue outgoingMessages; private final SettableBoolean isClosed; private Session websocketSession; private URI connectionURI; private int timeout_ms = 10000; // default timeout in milliseconds private boolean useDebugMessages = false; private WebsocketFailureListener failureListener; public WebsocketWrapper(){ outgoingMessages = new LinkedBlockingQueue(); isClosed = new SettableBoolean(false); } // must set this before run public void setConnectionURI(URI connectionURI){ this.connectionURI = connectionURI; } public void setFailureListener(WebsocketFailureListener failureListener){ this.failureListener = failureListener; } public void setUseDebugMessages(boolean useDebugMessages){ this.useDebugMessages = useDebugMessages; } // setup websocket and separate send thread public void run(){ ClientManager client = ClientManager.createClient(); // set the timeout for the initial connection Map clientProperties = client.getProperties(); clientProperties.put(ClientProperties.HANDSHAKE_TIMEOUT, timeout_ms); client.setAsyncSendTimeout(timeout_ms); // make the connection try { if(connectionURI == null) Log.e("websocket", "No connection URI set"); websocketSession = client.connectToServer(new MyEndpoint(useDebugMessages), connectionURI); } catch (DeploymentException e) { if(failureListener != null) failureListener.onConnectionFailure(e.toString()); } catch (IOException e) { // connection failure if(failureListener != null) failureListener.onConnectionFailure(e.toString() ); } String nextOutgoingMessage; while(this.isOpen() ){ synchronized(outgoingMessages){ while(this.isOpen() && outgoingMessages.isEmpty() ){ try{ outgoingMessages.wait(); } catch(Exception e){ if(failureListener != null) failureListener.onConnectionFailure(e.toString() ); } } // get a local copy and release lock nextOutgoingMessage = outgoingMessages.poll(); } // release lock and send // send is outside of lock to minimize blocking on main thread calling send if(this.isOpen() && nextOutgoingMessage != null){ try { websocketSession.getBasicRemote().sendText(nextOutgoingMessage); } catch (IOException e) { if(isOpen() ) { if (failureListener != null) failureListener.onConnectionFailure(e.toString()); } } } } } public void sendMessage(String message){ synchronized(outgoingMessages){ outgoingMessages.add(message); // signal to sending thread that outgoing content is available outgoingMessages.notify(); } } public boolean isOpen(){ synchronized(isClosed){ return (websocketSession != null) && websocketSession.isOpen() && !isClosed.getBoolean(); } } public void close(){ try { if(websocketSession != null) websocketSession.close(); } catch (IOException e) { // ignore exceptions when closing } synchronized(isClosed){ isClosed.setBoolean(true); } } }