Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(Android only) Fixes for a few problems and better callbacks #71

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
66 changes: 61 additions & 5 deletions src/android/Connection.java
Original file line number Diff line number Diff line change
@@ -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;


/**
Expand All @@ -24,7 +31,24 @@ public class Connection extends Thread {
private Boolean mustClose;
private String host;
private int port;
private CallbackContext callbackContext; //This is a bad practice. should be using handlers to send this to Socket Plugin
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.
Expand All @@ -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.
Expand Down Expand Up @@ -95,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();
}


Expand All @@ -109,8 +149,12 @@ public void run() {

// creating connection
try {
this.callbackSocket = new Socket(this.host, this.port);
this.writer = new PrintWriter(this.callbackSocket.getOutputStream(), true);
//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);
this.writer = new PrintWriter(this.callbackSocket.getOutputStream(), true);
this.reader = new BufferedReader(new InputStreamReader(callbackSocket.getInputStream()));

// receiving data chunk
Expand All @@ -128,17 +172,29 @@ public void run() {
}
}
} catch (Exception e) {
e.printStackTrace();
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");
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();
}

}

Expand Down
55 changes: 38 additions & 17 deletions src/android/SocketPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,12 @@ 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());
Expand Down Expand Up @@ -180,10 +179,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) {
Expand Down Expand Up @@ -224,6 +223,9 @@ private void disconnect (JSONArray args, CallbackContext callbackContext) {

// removing from pool
pool.remove(key);

//Triggering event
this.sendDisconnectedEvent(key);
}

// ending with success
Expand Down Expand Up @@ -257,11 +259,25 @@ 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.");
}

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();
Expand All @@ -273,14 +289,19 @@ 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);
}

public synchronized void sendConnectedEvent (String key, String ip, int port, Connection socket) {
this.pool.put(key, socket);

//TODO trigger an event later when needed
}
}
15 changes: 15 additions & 0 deletions www/socket.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down Expand Up @@ -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();