From 8f5f16c9e0113440a28492f9dec79c35cc79b0b3 Mon Sep 17 00:00:00 2001 From: Skandha Date: Mon, 6 Apr 2015 21:14:51 +0530 Subject: [PATCH 1/7] Now returns proper success and failure callback in connect function --- src/android/Connection.java | 55 ++++++++++++++++++++++++++++++++--- src/android/SocketPlugin.java | 7 ++--- 2 files changed, 54 insertions(+), 8 deletions(-) diff --git a/src/android/Connection.java b/src/android/Connection.java index f834dd7..afd6066 100644 --- a/src/android/Connection.java +++ b/src/android/Connection.java @@ -1,11 +1,18 @@ package com.tlantic.plugins.socket; +import android.util.Log; + import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; +import java.lang.Exception; +import java.lang.String; +import java.net.ConnectException; +import java.net.InetSocketAddress; import java.net.Socket; import java.net.UnknownHostException; +import org.apache.cordova.CallbackContext; /** @@ -24,7 +31,24 @@ public class Connection extends Thread { private Boolean mustClose; private String host; private int port; + private CallbackContext callbackContext; + private String buildKey; + + public String getBuildKey() { + return buildKey; + } + + public void setBuildKey(String buildKey) { + this.buildKey = buildKey; + } + public CallbackContext getCallbackContext() { + return callbackContext; + } + + public void setCallbackContext(CallbackContext callbackContext) { + this.callbackContext = callbackContext; + } /** * Creates a TCP socket connection object. @@ -43,6 +67,20 @@ public Connection(SocketPlugin pool, String host, int port) { this.hook = pool; } + /** + * Creates a TCP socket connection object. + * + * @param pool Object containing "sendMessage" method to be called as a callback for data receive. + * @param host Target host for socket connection. + * @param port Target port for socket connection + * @param callbackContext for sending callbacks + */ + public Connection(SocketPlugin pool, String host, int port, CallbackContext callbackContext, String buildKey) { + this(pool, host, port); + this.callbackContext = callbackContext; + this.buildKey = buildKey; + } + /** * Returns socket connection state. @@ -109,8 +147,10 @@ public void run() { // creating connection try { - this.callbackSocket = new Socket(this.host, this.port); - this.writer = new PrintWriter(this.callbackSocket.getOutputStream(), true); + this.callbackSocket = new Socket(); + this.callbackSocket.connect(new InetSocketAddress(this.host, this.port), 20000); + this.callbackContext.success(this.buildKey); + this.writer = new PrintWriter(this.callbackSocket.getOutputStream(), true); this.reader = new BufferedReader(new InputStreamReader(callbackSocket.getInputStream())); // receiving data chunk @@ -126,7 +166,9 @@ public void run() { System.out.print("## RECEIVED DATA: " + chunk); hook.sendMessage(this.host, this.port, chunk); } - } + } else { + + } } catch (Exception e) { e.printStackTrace(); } @@ -134,11 +176,16 @@ public void run() { } catch (UnknownHostException e1) { // TODO Auto-generated catch block + this.callbackContext.error(this.buildKey+" did not connect: unknown host"); e1.printStackTrace(); } catch (IOException e1) { // TODO Auto-generated catch block + this.callbackContext.error(this.buildKey+" did not connect: io host"); e1.printStackTrace(); - } + } catch (Exception el) { + this.callbackContext.error(this.buildKey+" did not connect: unknown error"); + el.printStackTrace(); + } } diff --git a/src/android/SocketPlugin.java b/src/android/SocketPlugin.java index 91f5e37..c5e52c1 100644 --- a/src/android/SocketPlugin.java +++ b/src/android/SocketPlugin.java @@ -95,13 +95,13 @@ private void connect (JSONArray args, CallbackContext callbackContext) { // creating connection if (this.pool.get(key) == null) { - socket = new Connection(this, host, port); + socket = new Connection(this, host, port, callbackContext, key); socket.start(); this.pool.put(key, socket); } // adding to pool - callbackContext.success(key); +// callbackContext.success(key); } catch (JSONException e) { callbackContext.error("Invalid parameters for 'connect' action: " + e.getMessage()); @@ -282,5 +282,4 @@ public void run() { }); } - -} \ No newline at end of file +} From 1609294bcc9a13797612b0a12e0323aeefe185f2 Mon Sep 17 00:00:00 2001 From: Skandha Date: Tue, 7 Apr 2015 10:15:38 +0530 Subject: [PATCH 2/7] Added socket disconnected callback - REQUIRES CLEANUP --- src/android/Connection.java | 36 ++++++++++++++++++++++++++--------- src/android/SocketPlugin.java | 29 ++++++++++++++++++++-------- www/socket.js | 15 +++++++++++++++ 3 files changed, 63 insertions(+), 17 deletions(-) diff --git a/src/android/Connection.java b/src/android/Connection.java index afd6066..418742f 100644 --- a/src/android/Connection.java +++ b/src/android/Connection.java @@ -31,7 +31,7 @@ public class Connection extends Thread { private Boolean mustClose; private String host; private int port; - private CallbackContext callbackContext; + private CallbackContext callbackContext; //This is a bad practice. should be using handlers to send this to Socket Plugin private String buildKey; public String getBuildKey() { @@ -147,9 +147,11 @@ public void run() { // creating connection try { + Log.d("now", "Initiating connection to socket"); this.callbackSocket = new Socket(); this.callbackSocket.connect(new InetSocketAddress(this.host, this.port), 20000); this.callbackContext.success(this.buildKey); + Log.d("now", "Connected to socket"); this.writer = new PrintWriter(this.callbackSocket.getOutputStream(), true); this.reader = new BufferedReader(new InputStreamReader(callbackSocket.getInputStream())); @@ -159,6 +161,7 @@ public void run() { try { if (this.isConnected()) { + Log.d("now", "reading......"); chunk = reader.readLine(); if (chunk != null) { @@ -167,25 +170,40 @@ public void run() { hook.sendMessage(this.host, this.port, chunk); } } else { - - } + Log.d("now", "Connection closed but still running"); + } } catch (Exception e) { - e.printStackTrace(); + //Only socket exception gets triggerred frequently + //TODO close the socket + //TODO this.mustClose = true + Log.d("now", "connection closed"); + + try { + this.callbackSocket.close(); + } catch (Exception closeException) { + closeException.printStackTrace(); + } + + hook.sendDisconnectedEvent(this.buildKey); + this.mustClose = true; } } } catch (UnknownHostException e1) { // TODO Auto-generated catch block - this.callbackContext.error(this.buildKey+" did not connect: unknown host"); + this.callbackContext.error(this.buildKey+" did not connect: unknown host"); + Log.d("now", "unknown host exception raised on connection"); e1.printStackTrace(); } catch (IOException e1) { // TODO Auto-generated catch block - this.callbackContext.error(this.buildKey+" did not connect: io host"); + this.callbackContext.error(this.buildKey+" did not connect: io host"); + Log.d("now", "io exception raised on connection"); e1.printStackTrace(); } catch (Exception el) { - this.callbackContext.error(this.buildKey+" did not connect: unknown error"); - el.printStackTrace(); - } + this.callbackContext.error(this.buildKey+" did not connect: unknown error"); + Log.d("now", "exception raised on connection"); + el.printStackTrace(); + } } diff --git a/src/android/SocketPlugin.java b/src/android/SocketPlugin.java index c5e52c1..1d1db31 100644 --- a/src/android/SocketPlugin.java +++ b/src/android/SocketPlugin.java @@ -31,6 +31,7 @@ public class SocketPlugin extends CordovaPlugin { @Override public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { + System.out.println("Skandha"); if (action.equals("connect")) { this.connect(args, callbackContext); return true; @@ -91,6 +92,7 @@ private void connect (JSONArray args, CallbackContext callbackContext) { // preparing parameters host = args.getString(0); port = args.getInt(1); + System.out.println("trying to connect to host: "+host+", "+port); key = this.buildKey(host, port); // creating connection @@ -262,6 +264,17 @@ private void disconnectAll (CallbackContext callbackContext) { callbackContext.success("All connections were closed."); } + private void sendEvent(final String eventTriggerCode) { + cordova.getActivity().runOnUiThread(new Runnable() { + + @Override + public void run() { + webView.loadUrl("javascript:" + eventTriggerCode); + } + + }); + } + /** * Callback for Connection object data receive. Relay information to javascript object method: window.tlantic.plugins.socket.receive(); @@ -273,13 +286,13 @@ private void disconnectAll (CallbackContext callbackContext) { public synchronized void sendMessage(String host, int port, String chunk) { final String receiveHook = "window.tlantic.plugins.socket.receive(\"" + host + "\"," + port + ",\"" + this.buildKey(host, port) + "\",\"" + chunk.replace("\"", "\\\"") + "\");"; - cordova.getActivity().runOnUiThread(new Runnable() { - - @Override - public void run() { - webView.loadUrl("javascript:" + receiveHook); - } - - }); + this.sendEvent(receiveHook); } + + public synchronized void sendDisconnectedEvent(String buildKey) { + final String receiveHook = "window.tlantic.plugins.socket.disconnectedEvent(\"" + buildKey + "\");"; + pool.remove(buildKey); + + this.sendEvent(receiveHook); + } } diff --git a/www/socket.js b/www/socket.js index 8add8da..b6a0dae 100644 --- a/www/socket.js +++ b/www/socket.js @@ -6,6 +6,7 @@ function Socket(){ 'use strict'; this.receiveHookName = 'SOCKET_RECEIVE_DATA_HOOK'; // *** Event name to act as "hook" for data receiving + this.disconnectedHookName = 'SOCKET_DISCONNECTED'; this.pluginRef = 'Socket'; // *** Plugin reference for Cordova.exec calls } @@ -57,4 +58,18 @@ Socket.prototype.receive = function (host, port, connectionId, chunk) { document.dispatchEvent(evReceive); }; + +Socket.prototype.disconnectedEvent = function(connectionId) { + var evReceive = document.createEvent('Events'); + + evReceive.initEvent(this.disconnectedHookName, true, true); + evReceive.metadata = { + connection: { + id: connectionId + } + }; + + document.dispatchEvent(evReceive); +}; + module.exports = new Socket(); From a1b89128c217bd96cba97dcd51e25cf7243ec396 Mon Sep 17 00:00:00 2001 From: Skandha Date: Tue, 7 Apr 2015 11:22:44 +0530 Subject: [PATCH 3/7] Fixed: even if connection fails, it is added to the pool hence returning success when isConnected is called --- src/android/Connection.java | 2 ++ src/android/SocketPlugin.java | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/android/Connection.java b/src/android/Connection.java index 418742f..e5e5be8 100644 --- a/src/android/Connection.java +++ b/src/android/Connection.java @@ -148,8 +148,10 @@ public void run() { // creating connection try { Log.d("now", "Initiating connection to socket"); + //This is a bad practice. should be using handlers to send this to SocketPlugin this.callbackSocket = new Socket(); this.callbackSocket.connect(new InetSocketAddress(this.host, this.port), 20000); + this.hook.sendConnectedEvent(this.buildKey, this.host, this.port, this); this.callbackContext.success(this.buildKey); Log.d("now", "Connected to socket"); this.writer = new PrintWriter(this.callbackSocket.getOutputStream(), true); diff --git a/src/android/SocketPlugin.java b/src/android/SocketPlugin.java index 1d1db31..88f67d9 100644 --- a/src/android/SocketPlugin.java +++ b/src/android/SocketPlugin.java @@ -99,7 +99,6 @@ private void connect (JSONArray args, CallbackContext callbackContext) { if (this.pool.get(key) == null) { socket = new Connection(this, host, port, callbackContext, key); socket.start(); - this.pool.put(key, socket); } // adding to pool @@ -295,4 +294,10 @@ public synchronized void sendDisconnectedEvent(String buildKey) { this.sendEvent(receiveHook); } + + public synchronized void sendConnectedEvent (String key, String ip, int port, Connection socket) { + this.pool.put(key, socket); + + //TODO trigger an event later when needed + } } From b19f21da870e08f414856c63554006da1b9d8f8d Mon Sep 17 00:00:00 2001 From: Skandha Date: Tue, 7 Apr 2015 15:19:06 +0530 Subject: [PATCH 4/7] Added immediate write flush and error checking --- src/android/Connection.java | 4 +++- src/android/SocketPlugin.java | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/android/Connection.java b/src/android/Connection.java index e5e5be8..32e979c 100644 --- a/src/android/Connection.java +++ b/src/android/Connection.java @@ -133,8 +133,10 @@ public void close() { * * @param data information to be sent */ - public void write(String data) { + public boolean write(String data) { this.writer.println(data); + this.writer.flush(); + return !this.writer.checkError(); } diff --git a/src/android/SocketPlugin.java b/src/android/SocketPlugin.java index 88f67d9..02393b3 100644 --- a/src/android/SocketPlugin.java +++ b/src/android/SocketPlugin.java @@ -181,10 +181,10 @@ private void send(JSONArray args, CallbackContext callbackContext) { } else { // write on output stream - socket.write(data); - - // ending send process - callbackContext.success(); + if(socket.write(data)) + callbackContext.success(); + else + callbackContext.error("Failed to send data"); } } catch (JSONException e) { From 5a6487f9bf453cd03dc22932af8522dac43478bf Mon Sep 17 00:00:00 2001 From: Skandha Date: Tue, 7 Apr 2015 15:25:35 +0530 Subject: [PATCH 5/7] Cleanup --- src/android/Connection.java | 21 ++++++++------------- src/android/SocketPlugin.java | 3 +-- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/src/android/Connection.java b/src/android/Connection.java index 32e979c..5158fda 100644 --- a/src/android/Connection.java +++ b/src/android/Connection.java @@ -149,13 +149,13 @@ public void run() { // creating connection try { - Log.d("now", "Initiating connection to socket"); + Log.d("connection", "Initiating connection to socket"); //This is a bad practice. should be using handlers to send this to SocketPlugin this.callbackSocket = new Socket(); this.callbackSocket.connect(new InetSocketAddress(this.host, this.port), 20000); this.hook.sendConnectedEvent(this.buildKey, this.host, this.port, this); this.callbackContext.success(this.buildKey); - Log.d("now", "Connected to socket"); + Log.d("connection", "Connected to socket"); this.writer = new PrintWriter(this.callbackSocket.getOutputStream(), true); this.reader = new BufferedReader(new InputStreamReader(callbackSocket.getInputStream())); @@ -165,7 +165,7 @@ public void run() { try { if (this.isConnected()) { - Log.d("now", "reading......"); + Log.d("connection", "reading......"); chunk = reader.readLine(); if (chunk != null) { @@ -173,14 +173,9 @@ public void run() { System.out.print("## RECEIVED DATA: " + chunk); hook.sendMessage(this.host, this.port, chunk); } - } else { - Log.d("now", "Connection closed but still running"); - } + } } catch (Exception e) { - //Only socket exception gets triggerred frequently - //TODO close the socket - //TODO this.mustClose = true - Log.d("now", "connection closed"); + Log.d("connection", "connection closed"); try { this.callbackSocket.close(); @@ -196,16 +191,16 @@ public void run() { } catch (UnknownHostException e1) { // TODO Auto-generated catch block this.callbackContext.error(this.buildKey+" did not connect: unknown host"); - Log.d("now", "unknown host exception raised on connection"); + Log.d("connection", "unknown host exception raised on connection"); e1.printStackTrace(); } catch (IOException e1) { // TODO Auto-generated catch block this.callbackContext.error(this.buildKey+" did not connect: io host"); - Log.d("now", "io exception raised on connection"); + Log.d("connection", "io exception raised on connection"); e1.printStackTrace(); } catch (Exception el) { this.callbackContext.error(this.buildKey+" did not connect: unknown error"); - Log.d("now", "exception raised on connection"); + Log.d("connection", "exception raised on connection"); el.printStackTrace(); } diff --git a/src/android/SocketPlugin.java b/src/android/SocketPlugin.java index 02393b3..d408ce9 100644 --- a/src/android/SocketPlugin.java +++ b/src/android/SocketPlugin.java @@ -31,7 +31,6 @@ public class SocketPlugin extends CordovaPlugin { @Override public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { - System.out.println("Skandha"); if (action.equals("connect")) { this.connect(args, callbackContext); return true; @@ -92,7 +91,7 @@ private void connect (JSONArray args, CallbackContext callbackContext) { // preparing parameters host = args.getString(0); port = args.getInt(1); - System.out.println("trying to connect to host: "+host+", "+port); + Log.d("connection", "trying to connect to host: "+host+", "+port); key = this.buildKey(host, port); // creating connection From 694d98c5b5396d3325da08d86d2532e050a65eab Mon Sep 17 00:00:00 2001 From: Skandha Date: Thu, 9 Apr 2015 12:26:35 +0530 Subject: [PATCH 6/7] Removing Log.d's --- src/android/Connection.java | 8 -------- src/android/SocketPlugin.java | 1 - 2 files changed, 9 deletions(-) diff --git a/src/android/Connection.java b/src/android/Connection.java index 5158fda..162756d 100644 --- a/src/android/Connection.java +++ b/src/android/Connection.java @@ -149,13 +149,11 @@ public void run() { // creating connection try { - Log.d("connection", "Initiating connection to socket"); //This is a bad practice. should be using handlers to send this to SocketPlugin this.callbackSocket = new Socket(); this.callbackSocket.connect(new InetSocketAddress(this.host, this.port), 20000); this.hook.sendConnectedEvent(this.buildKey, this.host, this.port, this); this.callbackContext.success(this.buildKey); - Log.d("connection", "Connected to socket"); this.writer = new PrintWriter(this.callbackSocket.getOutputStream(), true); this.reader = new BufferedReader(new InputStreamReader(callbackSocket.getInputStream())); @@ -165,7 +163,6 @@ public void run() { try { if (this.isConnected()) { - Log.d("connection", "reading......"); chunk = reader.readLine(); if (chunk != null) { @@ -175,8 +172,6 @@ public void run() { } } } catch (Exception e) { - Log.d("connection", "connection closed"); - try { this.callbackSocket.close(); } catch (Exception closeException) { @@ -191,16 +186,13 @@ public void run() { } catch (UnknownHostException e1) { // TODO Auto-generated catch block this.callbackContext.error(this.buildKey+" did not connect: unknown host"); - Log.d("connection", "unknown host exception raised on connection"); e1.printStackTrace(); } catch (IOException e1) { // TODO Auto-generated catch block this.callbackContext.error(this.buildKey+" did not connect: io host"); - Log.d("connection", "io exception raised on connection"); e1.printStackTrace(); } catch (Exception el) { this.callbackContext.error(this.buildKey+" did not connect: unknown error"); - Log.d("connection", "exception raised on connection"); el.printStackTrace(); } diff --git a/src/android/SocketPlugin.java b/src/android/SocketPlugin.java index d408ce9..0c79444 100644 --- a/src/android/SocketPlugin.java +++ b/src/android/SocketPlugin.java @@ -91,7 +91,6 @@ private void connect (JSONArray args, CallbackContext callbackContext) { // preparing parameters host = args.getString(0); port = args.getInt(1); - Log.d("connection", "trying to connect to host: "+host+", "+port); key = this.buildKey(host, port); // creating connection From 28b916228ad4e0b8788dec40906b5555524c8527 Mon Sep 17 00:00:00 2001 From: Skandha Date: Sat, 11 Apr 2015 18:34:19 +0530 Subject: [PATCH 7/7] Sending disconnected event when disconnect or disconnectAll is called --- src/android/SocketPlugin.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/android/SocketPlugin.java b/src/android/SocketPlugin.java index 0c79444..3d5ec52 100644 --- a/src/android/SocketPlugin.java +++ b/src/android/SocketPlugin.java @@ -223,6 +223,9 @@ private void disconnect (JSONArray args, CallbackContext callbackContext) { // removing from pool pool.remove(key); + + //Triggering event + this.sendDisconnectedEvent(key); } // ending with success @@ -256,6 +259,9 @@ private void disconnectAll (CallbackContext callbackContext) { // removing from pool this.pool.remove(pairs.getKey()); + + //Triggering event + this.sendDisconnectedEvent(pairs.getKey()); } callbackContext.success("All connections were closed.");