package plugin.socket.io; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import org.apache.cordova.CallbackContext; import org.apache.cordova.CordovaPlugin; import org.apache.cordova.PluginResult; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.annotation.SuppressLint; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.graphics.BitmapFactory; import android.util.Base64; import android.util.Log; import com.github.nkzawa.emitter.Emitter; import com.github.nkzawa.socketio.client.Ack; import com.github.nkzawa.socketio.client.IO; import com.github.nkzawa.socketio.client.Socket; public class SocketIO extends CordovaPlugin { private Socket socket; private Map<Integer, Emitter.Listener> LISTENERS = new HashMap<Integer, Emitter.Listener>(); public boolean execute(final String action, final JSONArray args, final CallbackContext callbackContext) throws JSONException { try { Method method = this.getClass().getDeclaredMethod(action, JSONArray.class, CallbackContext.class); method.setAccessible(true); method.invoke(this, args, callbackContext); return true; } catch (Exception e) { e.printStackTrace(); callbackContext.error(e.getMessage()); return false; } } @SuppressWarnings("unused") private void connect(final JSONArray args, final CallbackContext callbackContext) throws JSONException { String uri; try { uri = args.getString(0); Log.d("CordovaLog", "--uri: " + uri); socket = IO.socket(uri); socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() { @Override public void call(Object... args) { Log.d("CordovaLog", "--connect: success"); callbackContext.success(); } }); socket.on(Socket.EVENT_CONNECT_ERROR, new Emitter.Listener() { @Override public void call(Object... args) { Log.d("CordovaLog", "--connect: error"); callbackContext.error("" + args[0]); } }); socket.connect(); } catch (Exception e) { e.printStackTrace(); callbackContext.error(e.getMessage()); } } @SuppressWarnings("unused") private void on(final JSONArray args, final CallbackContext callbackContext) throws JSONException { String event = args.getString(0); final Boolean needKeepCallback = args.getBoolean(1); Emitter.Listener listener = new Emitter.Listener() { @Override public void call(Object... args) { PluginResult pluginResult = makePluginResult(PluginResult.Status.OK, args); pluginResult.setKeepCallback(needKeepCallback); callbackContext.sendPluginResult(pluginResult); } }; int hashCode = listener.hashCode(); Log.d("CordovaLog", "callbackId=" + callbackContext.getCallbackId() + ",needKeep=" + needKeepCallback); this.socket.on(event, listener); PluginResult pluginResult; if (needKeepCallback) { pluginResult = new PluginResult(PluginResult.Status.OK, hashCode); pluginResult.setKeepCallback(true); LISTENERS.put(hashCode, listener); callbackContext.sendPluginResult(pluginResult); } } @SuppressWarnings("unused") private void off(final JSONArray args, final CallbackContext callbackContext) throws JSONException { if (args.length() == 0) { this.socket.off(); callbackContext.success(); return; } String eventName = args.getString(0); if (args.length() == 1) { this.socket.off(eventName); callbackContext.success(); return; } int hashCode = args.getInt(1); if (LISTENERS.containsKey(hashCode)) { Emitter.Listener listener = LISTENERS.remove(hashCode); this.socket.off(eventName, listener); } } @SuppressWarnings("unused") private void emit(final JSONArray args, final CallbackContext callbackContext) throws JSONException { // Get emit parameters boolean needCallback = args.getBoolean(0); String event = args.getString(1); Object[] params = new Object[args.length() - 2]; for (int i = 2; i < args.length(); i++) { params[i - 2] = args.get(i); } Class<Socket> socketClass = (Class<Socket>) socket.getClass(); try { Method emit = null; if (needCallback) { emit = socketClass.getMethod("emit", String.class, Object[].class, Ack.class); emit.invoke(socket, event, params, new Ack() { @Override public void call(Object... args) { callbackContext.sendPluginResult(makePluginResult(PluginResult.Status.OK, args)); } }); } else { emit = socketClass.getMethod("emit", String.class, Object[].class); emit.invoke(socket, event, params); } } catch (Exception e) { e.printStackTrace(); } } private PluginResult makePluginResult(PluginResult.Status status, Object... args) { if (args.length == 0) { return new PluginResult(status); } if (args.length == 1) { Object args0 = args[0]; if (args0 instanceof JSONObject) { return new PluginResult(status, (JSONObject) args0); } if (args0 instanceof JSONArray) { return new PluginResult(status, (JSONArray) args0); } if (args0 instanceof Integer) { return new PluginResult(status, (Integer) args0); } if (args0 instanceof String) { return new PluginResult(status, (String) args0); } try { return new PluginResult(status, toByteArray(args0)); } catch (IOException e) { return new PluginResult(status, ((String) args0).getBytes()); } } JSONArray result = new JSONArray(); for (int i = 0; i < args.length; i++) { result.put(args[i]); } return new PluginResult(status, result); } //toByteArray and toObject are taken from: http://tinyurl.com/69h8l7x public static byte[] toByteArray(Object obj) throws IOException { byte[] bytes = null; ByteArrayOutputStream bos = null; ObjectOutputStream oos = null; try { bos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(bos); oos.writeObject(obj); oos.flush(); bytes = bos.toByteArray(); } finally { if (oos != null) { oos.close(); } if (bos != null) { bos.close(); } } return bytes; } @SuppressWarnings("unused") private void getWebPfromBase64EncodedImage(final JSONArray args, final CallbackContext callbackContext) { cordova.getThreadPool().execute(new Runnable(){ @SuppressLint("NewApi") @Override public void run() { String base64EncodedImage = null; try { base64EncodedImage = args.getString(0); } catch (JSONException e1) { e1.printStackTrace(); } if (base64EncodedImage == null) { callbackContext.error("Cannot get image data"); return; } String[] tmp = base64EncodedImage.split(","); byte[] byteArray= Base64.decode(tmp[1], Base64.DEFAULT); Bitmap bitmap= null; try { bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length); } catch (Exception e) { e.printStackTrace(); } if (bitmap == null) { callbackContext.error("Cannot get image"); return; } ByteArrayOutputStream out = new ByteArrayOutputStream(); bitmap.compress(CompressFormat.WEBP, 75, out); byte[] webpByteArray = out.toByteArray(); callbackContext.success(webpByteArray); //String result = "data:image/webp;base64," + Base64.encodeToString(webpByteArray, Base64.NO_WRAP); //callbackContext.success(result); /* int bytes = smallBitmap.getByteCount(); ByteBuffer buffer = ByteBuffer.allocate(bytes); smallBitmap.copyPixelsToBuffer(buffer); byte[] pixels = buffer.array(); int height = smallBitmap.getHeight(); int width = smallBitmap.getWidth(); int stride = bytes / height; int quality = 98; byte[] webpByteArray = libwebp.WebPEncodeRGBA(pixels, width, height, stride, quality); String result = "data:image/webp;base64," + Base64.encodeToString(webpByteArray, Base64.NO_WRAP); callbackContext.success(result); smallBitmap.recycle(); bitmap.recycle(); smallBitmap = null; bitmap = null; */ } }); } }