11package com .codebutler .android_websockets ;
22
3+ import android .os .Handler ;
4+ import android .os .HandlerThread ;
35import android .text .TextUtils ;
46import android .util .Base64 ;
57import android .util .Log ;
@@ -27,9 +29,11 @@ public class WebSocketClient {
2729 private static final String TAG = "WebSocketClient" ;
2830
2931 private URI mURI ;
30- private Handler mHandler ;
32+ private Listener mListener ;
3133 private Socket mSocket ;
3234 private Thread mThread ;
35+ private HandlerThread mHandlerThread ;
36+ private Handler mHandler ;
3337 private List <BasicNameValuePair > mExtraHeaders ;
3438 private HybiParser mParser ;
3539
@@ -41,15 +45,19 @@ public static void setTrustManagers(TrustManager[] tm) {
4145 sTrustManagers = tm ;
4246 }
4347
44- public WebSocketClient (URI uri , Handler handler , List <BasicNameValuePair > extraHeaders ) {
48+ public WebSocketClient (URI uri , Listener listener , List <BasicNameValuePair > extraHeaders ) {
4549 mURI = uri ;
46- mHandler = handler ;
50+ mListener = listener ;
4751 mExtraHeaders = extraHeaders ;
4852 mParser = new HybiParser (this );
53+
54+ mHandlerThread = new HandlerThread ("websocket-thread" );
55+ mHandlerThread .start ();
56+ mHandler = new Handler (mHandlerThread .getLooper ());
4957 }
5058
51- public Handler getHandler () {
52- return mHandler ;
59+ public Listener getListener () {
60+ return mListener ;
5361 }
5462
5563 public void connect () {
@@ -69,7 +77,7 @@ public void run() {
6977 }
7078
7179 String originScheme = mURI .getScheme ().equals ("wss" ) ? "https" : "http" ;
72- URI origin = new URI (originScheme , mURI .getSchemeSpecificPart (), null );
80+ URI origin = new URI (originScheme , "//" + mURI .getHost (), null );
7381
7482 SocketFactory factory = mURI .getScheme ().equals ("wss" ) ? getSSLSocketFactory () : SocketFactory .getDefault ();
7583 mSocket = factory .createSocket (mURI .getHost (), port );
@@ -94,7 +102,9 @@ public void run() {
94102
95103 // Read HTTP response status line.
96104 StatusLine statusLine = parseStatusLine (readLine (stream ));
97- if (statusLine .getStatusCode () != HttpStatus .SC_SWITCHING_PROTOCOLS ) {
105+ if (statusLine == null ) {
106+ throw new HttpException ("Received no reply from server." );
107+ } else if (statusLine .getStatusCode () != HttpStatus .SC_SWITCHING_PROTOCOLS ) {
98108 throw new HttpResponseException (statusLine .getStatusCode (), statusLine .getReasonPhrase ());
99109 }
100110
@@ -107,32 +117,42 @@ public void run() {
107117 }
108118 }
109119
110- mHandler .onConnect ();
120+ mListener .onConnect ();
111121
112122 // Now decode websocket frames.
113123 mParser .start (stream );
114124
115125 } catch (EOFException ex ) {
116126 Log .d (TAG , "WebSocket EOF!" , ex );
117- mHandler .onDisconnect (0 , "EOF" );
127+ mListener .onDisconnect (0 , "EOF" );
118128
119129 } catch (SSLException ex ) {
120130 // Connection reset by peer
121131 Log .d (TAG , "Websocket SSL error!" , ex );
122- mHandler .onDisconnect (0 , "SSL" );
132+ mListener .onDisconnect (0 , "SSL" );
123133
124134 } catch (Exception ex ) {
125- mHandler .onError (ex );
135+ mListener .onError (ex );
126136 }
127137 }
128138 });
129139 mThread .start ();
130140 }
131141
132- public void disconnect () throws IOException {
142+ public void disconnect () {
133143 if (mSocket != null ) {
134- mSocket .close ();
135- mSocket = null ;
144+ mHandler .post (new Runnable () {
145+ @ Override
146+ public void run () {
147+ try {
148+ mSocket .close ();
149+ mSocket = null ;
150+ } catch (IOException ex ) {
151+ Log .d (TAG , "Error while disconnecting" , ex );
152+ mListener .onError (ex );
153+ }
154+ }
155+ });
136156 }
137157 }
138158
@@ -145,11 +165,14 @@ public void send(byte[] data) {
145165 }
146166
147167 private StatusLine parseStatusLine (String line ) {
168+ if (TextUtils .isEmpty (line )) {
169+ return null ;
170+ }
148171 return BasicLineParser .parseStatusLine (line , new BasicLineParser ());
149172 }
150173
151174 private Header parseHeader (String line ) {
152- return BasicLineParser .parseHeader (line , new BasicLineParser ());
175+ return BasicLineParser .parseHeader (line , new BasicLineParser ());
153176 }
154177
155178 // Can't use BufferedReader because it buffers past the HTTP data.
@@ -180,19 +203,24 @@ private String createSecret() {
180203 return Base64 .encodeToString (nonce , Base64 .DEFAULT ).trim ();
181204 }
182205
183- void sendFrame (byte [] frame ) {
184- try {
185- synchronized (mSendLock ) {
186- OutputStream outputStream = mSocket .getOutputStream ();
187- outputStream .write (frame );
188- outputStream .flush ();
206+ void sendFrame (final byte [] frame ) {
207+ mHandler .post (new Runnable () {
208+ @ Override
209+ public void run () {
210+ try {
211+ synchronized (mSendLock ) {
212+ OutputStream outputStream = mSocket .getOutputStream ();
213+ outputStream .write (frame );
214+ outputStream .flush ();
215+ }
216+ } catch (IOException e ) {
217+ mListener .onError (e );
218+ }
189219 }
190- } catch (IOException e ) {
191- mHandler .onError (e );
192- }
220+ });
193221 }
194222
195- public interface Handler {
223+ public interface Listener {
196224 public void onConnect ();
197225 public void onMessage (String message );
198226 public void onMessage (byte [] data );
0 commit comments