diff --git a/app/build.gradle b/app/build.gradle index 44ce8e8168fd35852be13dfa0a75d861ff50bafc..570367950b18f699e4dec692eaa60f7f0025eabe 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -4,11 +4,13 @@ apply plugin: 'me.tatarka.retrolambda' android { compileSdkVersion 25 + //noinspection GradleDependency buildToolsVersion "25.0.2" defaultConfig { applicationId "com.tecsynt.nynja" minSdkVersion 17 + //noinspection OldTargetApi targetSdkVersion 25 versionCode 1 versionName "0.0.01" @@ -83,6 +85,7 @@ dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) // Support libraries + compile "com.android.support:support-v4:$supportLibraryVersion" compile "com.android.support:appcompat-v7:$supportLibraryVersion" compile "com.android.support:design:$supportLibraryVersion" compile 'com.android.support.constraint:constraint-layout:1.0.2' @@ -119,6 +122,13 @@ dependencies { compile "io.reactivex.rxjava2:rxandroid:2.0.1" compile "io.reactivex.rxjava2:rxjava:$rxJavaVersion" +// MQTT + compile 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.0.2' + compile ('org.eclipse.paho:org.eclipse.paho.android.service:1.0.2') { + exclude module: 'support-v4' + } + + androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a77ca1903cba422b1c460bf94d927758282e499b..544eb9fd4531856c0832f3ba99e0ae0e95a1f1ee 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,15 +1,15 @@ + xmlns:android="http://schemas.android.com/apk/res/android"> - - - + + + - - - + + + + android:supportsRtl="true" + android:theme="@style/AppTheme"> + + + + - + - + - + - + - + \ No newline at end of file diff --git a/app/src/main/java/com/tecsynt/nynja/server/PahoService.java b/app/src/main/java/com/tecsynt/nynja/server/PahoService.java new file mode 100644 index 0000000000000000000000000000000000000000..8a8d645e560e28a0844a1df8051704c8b69e4617 --- /dev/null +++ b/app/src/main/java/com/tecsynt/nynja/server/PahoService.java @@ -0,0 +1,95 @@ +package com.tecsynt.nynja.server; + +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.os.IBinder; +import android.support.annotation.Nullable; + +import org.eclipse.paho.android.service.MqttAndroidClient; +import org.eclipse.paho.client.mqttv3.IMqttActionListener; +import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken; +import org.eclipse.paho.client.mqttv3.IMqttToken; +import org.eclipse.paho.client.mqttv3.MqttCallback; +import org.eclipse.paho.client.mqttv3.MqttConnectOptions; +import org.eclipse.paho.client.mqttv3.MqttException; +import org.eclipse.paho.client.mqttv3.MqttMessage; + +import timber.log.Timber; + + +public class PahoService extends Service { + private static final String TAG = "PahoService "; + private static final String SERVER_URL = "tcp://ns.synrc.com:1883"; //1883 default port for mqtt + private static final String DEFAULT_CLIENT_ID = "emqttd_" + System.currentTimeMillis(); + private static final String USERNAME_TO_API = "api"; + + public static Intent newInstance(Context context) { + return new Intent(context, PahoService.class); + } + + @Override + public void onCreate() { + super.onCreate(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + connectToServer(); + return START_STICKY; + } + + @Nullable + @Override + public IBinder onBind(Intent intent) { + //TODO create connection to activity + return null; + } + + private void connectToServer() { + MqttAndroidClient serverClient = new MqttAndroidClient(getApplicationContext(), SERVER_URL, DEFAULT_CLIENT_ID); + serverClient.setCallback(new MqttCallback() { + + @Override + public void connectionLost(Throwable cause) { + Timber.e(cause); + } + + @Override + public void messageArrived(String topic, MqttMessage message) throws Exception { + Timber.d(TAG + "Message arrived, Topic:" + topic + ", Message:" + message.toString()); + } + + @Override + public void deliveryComplete(IMqttDeliveryToken token) { + Timber.d(TAG + "Deliver of message complete" + token); + } + }); + + MqttConnectOptions mqttConnectOptions = new MqttConnectOptions(); + mqttConnectOptions.setUserName(USERNAME_TO_API); + mqttConnectOptions.setCleanSession(false); + try { + serverClient.connect(mqttConnectOptions, null, new IMqttActionListener() { + @Override + public void onSuccess(IMqttToken asyncActionToken) { + Timber.d(TAG + "connect success"); + } + + + @Override + public void onFailure(IMqttToken asyncActionToken, Throwable exception) { + Timber.e(exception); + Timber.d(TAG + exception.toString()); + } + }); + } catch (MqttException e) { + e.printStackTrace(); + } + } +} diff --git a/app/src/main/java/com/tecsynt/nynja/server/com/softwarejoint/bert/Bert.java b/app/src/main/java/com/tecsynt/nynja/server/com/softwarejoint/bert/Bert.java new file mode 100644 index 0000000000000000000000000000000000000000..987023d8a61c4fc9048d445fed83b10f71be91a7 --- /dev/null +++ b/app/src/main/java/com/tecsynt/nynja/server/com/softwarejoint/bert/Bert.java @@ -0,0 +1,115 @@ +package com.tecsynt.nynja.server.com.softwarejoint.bert; + +import android.annotation.SuppressLint; + +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.HashMap; + +abstract class Bert { + + Charset utf8Charset; + + boolean encodeStringAsBinary; + boolean encodeMapKeysAsAtom; + boolean encodeMapKeysAsString; + boolean encodeMapAsPropList; + + boolean decodeAtomAsString; + boolean decodePropListsAsMap; + boolean decodeMapKeysAsString; + int maxMapElements; + + DistributionHeader.VERSION minorVersion; + + private ArrayList keys; + + Bert(){ + minorVersion = DistributionHeader.VERSION.NEW; + utf8Charset = Charset.forName("UTF-8"); + + encodeStringAsBinary = false; + encodeMapKeysAsAtom = false; + encodeMapKeysAsString = false; + encodeMapAsPropList = false; + + decodeAtomAsString = false; + decodePropListsAsMap = false; + + maxMapElements = 1000; + } + + public static BertEncoder setupEncoder(){ + return new BertEncoder(); + } + + public static BertDecoder setupDecoder(){ + return new BertDecoder(); + } + + public BertEncoder withBufferSize(int bufferSize){ + setBufferSize(bufferSize); + return (BertEncoder) this; + } + + public void setErlangMinorVersion(DistributionHeader.VERSION minorVersion){ + this.minorVersion = minorVersion; + } + + public BertEncoder withEncodeStringAsBinary(boolean encodeStringAsBinary){ + this.encodeStringAsBinary = encodeStringAsBinary; + return (BertEncoder) this; + } + + public BertEncoder withEncodeMapAsPropList(boolean encodeMapAsPropList){ + this.encodeMapAsPropList = encodeMapAsPropList; + return (BertEncoder) this; + } + + public BertEncoder withEncodeMapKeysAsAtom(boolean encodeMapKeysAsAtom){ + this.encodeMapKeysAsAtom = encodeMapKeysAsAtom; + return (BertEncoder) this; + } + + public BertEncoder withEncodeMapKeysAsString(boolean encodeMapKeysAsString){ + this.encodeMapKeysAsString = encodeMapKeysAsString; + return (BertEncoder) this; + } + + public BertDecoder withDecodeAtomAsString(boolean decodeAtomAsString){ + this.decodeAtomAsString = decodeAtomAsString; + return (BertDecoder) this; + } + + public BertDecoder withDecodePropListsAsMap(boolean decodePropListsAsMap){ + this.decodePropListsAsMap = decodePropListsAsMap; + return (BertDecoder) this; + } + + public BertDecoder withDecodeMapKeysAsString(boolean decodeMapKeysAsString){ + this.decodeMapKeysAsString = decodeMapKeysAsString; + return (BertDecoder) this; + } + + public BertDecoder withMaxMapElements(int maxMapElements){ + this.maxMapElements = maxMapElements; + return (BertDecoder) this; + } + + public BertDecoder addBinaryValuesAsStringForKey(Object key){ + if (keys == null) { + keys = new ArrayList<>(); + } + keys.add(key); + return (BertDecoder) this; + } + + @SuppressWarnings("SimplifiableIfStatement") + boolean shouldDecodeBinaryAsStringForKey(Object key){ + if (keys == null) return false; + return keys.contains(key); + } + + protected void setBufferSize(int bufferSize) { + } +} diff --git a/app/src/main/java/com/tecsynt/nynja/server/com/softwarejoint/bert/BertAtom.java b/app/src/main/java/com/tecsynt/nynja/server/com/softwarejoint/bert/BertAtom.java new file mode 100644 index 0000000000000000000000000000000000000000..1ed50e9f39107d34e71bb37f6866bbea547b2827 --- /dev/null +++ b/app/src/main/java/com/tecsynt/nynja/server/com/softwarejoint/bert/BertAtom.java @@ -0,0 +1,30 @@ +package com.tecsynt.nynja.server.com.softwarejoint.bert; + +import android.support.annotation.NonNull; +import android.text.TextUtils; + +public class BertAtom{ + + private static final int ATOM_EXT_MAX_LEN = 255; + + private String atom; + + BertAtom(@NonNull String atom) throws IllegalArgumentException{ + if (TextUtils.isEmpty(atom)) { + throw new IllegalArgumentException("Atom cannot be null"); + } + if (atom.length() > ATOM_EXT_MAX_LEN) { + throw new IllegalArgumentException("Atom max length can be only " + ATOM_EXT_MAX_LEN); + } + this.atom = atom; + } + + public String get() { + return atom; + } + + @Override + public String toString() { + return atom; + } +} diff --git a/app/src/main/java/com/tecsynt/nynja/server/com/softwarejoint/bert/BertDecoder.java b/app/src/main/java/com/tecsynt/nynja/server/com/softwarejoint/bert/BertDecoder.java new file mode 100644 index 0000000000000000000000000000000000000000..e3f696afd0ada2062e616ada24a8cb23aa613cf7 --- /dev/null +++ b/app/src/main/java/com/tecsynt/nynja/server/com/softwarejoint/bert/BertDecoder.java @@ -0,0 +1,272 @@ +package com.tecsynt.nynja.server.com.softwarejoint.bert; + +import android.text.TextUtils; + +import java.io.InvalidObjectException; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Objects; + +@SuppressWarnings("WeakerAccess") +public class BertDecoder extends Bert implements DistributionHeader { + + private ByteBuffer buffer; + private static final BigInteger MAX_LONG_VAL = BigInteger.valueOf(Long.MAX_VALUE); + + public Object decodeAny(byte[] data) throws InvalidObjectException { + buffer = ByteBuffer.wrap(data); + + switch (buffer.get()) { + case MAGIC: + break; + default: + throw new InvalidObjectException("Invalid Format"); + } + + return decode(); + } + + private Object decode() throws InvalidObjectException { + buffer.mark(); + switch (buffer.get()) { + case NIL_EXT: + return null; + case SMALL_INTEGER_EXT: + return decodeShortOrByte(); + case INTEGER_EXT: + return decodeInteger(); + case FLOAT_EXT: + return decodeDoubleOrFloat(VERSION.OLD); + case NEW_FLOAT_EXT: + return decodeDoubleOrFloat(VERSION.NEW); + case SMALL_BIG_EXT: + return decodeLongOrBigInteger(SMALL_BIG_EXT); + case LARGE_BIG_EXT: + return decodeLongOrBigInteger(LARGE_BIG_EXT); + case ATOM_EXT: + return decodeAtom(ATOM_EXT); + case SMALL_ATOM_EXT: + return decodeAtom(SMALL_ATOM_EXT); + case STRING_EXT: + return decodeString(); + case BINARY_EXT: + return decodeBinary(); + case LIST_EXT: + return decodeList(); + case SMALL_TUPLE_EXT: + return decodeTuple(SMALL_TUPLE_EXT); + case LARGE_TUPLE_EXT: + return decodeTuple(LARGE_TUPLE_EXT); + case MAP_EXT: + return decodeMap(); + default: + buffer.reset(); + throw new InvalidObjectException("Invalid Type " + buffer.get()); + } + } + + private Object decodeShortOrByte() { + Short s = getUnsignedByte(); + if (Byte.MIN_VALUE <= s && s <= Byte.MAX_VALUE){ + return s.byteValue(); + } + + return s; + } + + private Integer decodeInteger() { + return buffer.getInt(); + } + + private Object decodeDoubleOrFloat(VERSION minorVersion) { + Double d = null; + + switch (minorVersion) { + case OLD: + d = Double.valueOf(decodeString(FLOAT_LENGTH)); + break; + case NEW: + d = buffer.getDouble(); + break; + } + + if (Float.MIN_VALUE <= d && d <= Float.MAX_VALUE) return d.floatValue(); + return d; + } + + private Object decodeLongOrBigInteger(int tag) throws InvalidObjectException { + int byteCount = 0; + + switch (tag) { + case SMALL_BIG_EXT: + byteCount = getUnsignedByte(); + break; + case LARGE_BIG_EXT: + long count = getUnsignedInt(); + if (count > Integer.MAX_VALUE) { + throw new InvalidObjectException("Max byte array size exceeded"); + } + byteCount = (int) count; + break; + } + + int signum = (buffer.get() == 0) ? 1 : -1; + byte[] value = new byte[byteCount]; + for (int i = byteCount; i > 0; i--) { + value[i - 1] = buffer.get(); + } + + BigInteger bigInteger = new BigInteger(signum, value); + + if (bigInteger.compareTo(MAX_LONG_VAL) == 1) return bigInteger; + return bigInteger.longValue(); + } + + private Object decodeAtom(int tag) { + int atomLength = 0; + String atom = null; + + switch (tag){ + case ATOM_EXT: + atomLength = getUnsignedShort(); + break; + case SMALL_ATOM_EXT: + atomLength = getUnsignedByte(); + break; + } + + if (atomLength > 0){ + atom = decodeString(atomLength); + } + + if (TextUtils.isEmpty(atom)) return null; + + if ("true".equalsIgnoreCase(atom)) return Boolean.TRUE; + else if ("false".equalsIgnoreCase(atom)) return Boolean.FALSE; + + if (decodeAtomAsString) return atom; + return new BertAtom(atom); + } + + private String decodeString(){ + int byteCount = getUnsignedShort(); + return decodeString(byteCount); + } + + private byte[] decodeBinary(){ + long byteCount = getUnsignedInt(); + byte[] data = new byte[(int) byteCount]; + buffer.get(data); + return data; + } + + private Object decodeList() throws InvalidObjectException { + long numElements = getUnsignedInt(); + boolean canDecodeAsMap = decodePropListsAsMap; + + ArrayList list = new ArrayList<>(); + + for(int i = 0; i < numElements; i++){ + Object decoded = decode(); + canDecodeAsMap = + canDecodeAsMap && + decoded instanceof BertTuple && ((BertTuple) decoded).isKV(); + list.add(decoded); + } + + buffer.mark(); + if (buffer.get() != NIL_EXT) buffer.reset(); + + if (canDecodeAsMap){ + Map map = new LinkedHashMap<>(); + for (int i = 0; i < list.size(); i++){ + BertTuple tuple = (BertTuple) list.get(i); + map.put(tuple.get(0), tuple.get(1)); + } + + return map; + } + return list; + } + + private BertTuple decodeTuple(int tag) throws InvalidObjectException { + long elements = 0; + + switch (tag){ + case SMALL_TUPLE_EXT: + elements = getUnsignedByte(); + break; + case LARGE_TUPLE_EXT: + elements = getUnsignedInt(); + break; + } + + BertTuple tuple = new BertTuple(); + for(long i = 0; i < elements; i ++){ + tuple.add(decode()); + } + + return tuple; + } + + private Map decodeMap() throws InvalidObjectException { + Map map = new LinkedHashMap<>(); + long elements = getUnsignedInt(); + + if (elements > maxMapElements){ + throw new InvalidObjectException("Too many elements in map"); + } + + for (long i = 0; i < elements; i++){ + Object key = decode(); + Object value = decode(); + + if (key == null) continue; + + key = getMapKey(key); + value = getMapValue(key, value); + map.put(key, value); + } + + return map; + } + + private Object getMapKey(Object key){ + if (!decodeMapKeysAsString) return key; + + if (key instanceof String) return key; + if (key instanceof BertAtom) return ((BertAtom) key).get(); + if (key instanceof byte[]) new String((byte[]) key, utf8Charset); + return key.toString(); + } + + private Object getMapValue(Object key, Object value){ + if (value == null) return null; + + if (shouldDecodeBinaryAsStringForKey(key)){ + return new String((byte[]) value, utf8Charset); + } + return value; + } + + private String decodeString(int byteCount){ + int position = buffer.position(); + buffer.position(buffer.position() + byteCount); + return new String(buffer.array(), position, byteCount); + } + + private short getUnsignedByte() { + return ((short) (buffer.get() & 0xff)); + } + + private int getUnsignedShort() { + return (buffer.getShort() & 0xffff); + } + + private long getUnsignedInt() { + return ((long) buffer.getInt() & 0xffffffffL); + } +} diff --git a/app/src/main/java/com/tecsynt/nynja/server/com/softwarejoint/bert/BertEncoder.java b/app/src/main/java/com/tecsynt/nynja/server/com/softwarejoint/bert/BertEncoder.java new file mode 100644 index 0000000000000000000000000000000000000000..3e8d25502e8cccbc5425ed3da3e2a991b19ad97d --- /dev/null +++ b/app/src/main/java/com/tecsynt/nynja/server/com/softwarejoint/bert/BertEncoder.java @@ -0,0 +1,244 @@ +package com.tecsynt.nynja.server.com.softwarejoint.bert; + +import java.lang.reflect.Array; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.util.List; +import java.util.Map; + +@SuppressWarnings("WeakerAccess") +public final class BertEncoder extends Bert implements DistributionHeader{ + + private ByteBuffer buffer; + + @Override + protected void setBufferSize(int bufferSize) { + buffer = ByteBuffer.allocate(bufferSize); + } + + public byte[] encodeAny(Object any){ + buffer.clear(); + buffer.put(MAGIC); + encode(any); + byte[] encodedData = new byte[buffer.position()]; + buffer.flip(); + buffer.get(encodedData); + return encodedData; + } + + @SuppressWarnings("unchecked") + private void encode(Object any){ + if (any == null){ + encodeNull(); + } else if (any instanceof Byte) { + encodeByte((Byte) any); + } else if (any instanceof Short){ + encodeInteger(((Short) any).intValue()); + } else if (any instanceof Integer){ + encodeInteger((Integer) any); + } else if (any instanceof Float) { + encodeDouble(((Float) any).doubleValue()); + } else if (any instanceof Double) { + encodeDouble((Double) any); + } else if (any instanceof Long){ + encodeLong((Long) any); + } else if (any instanceof BigInteger){ + encodeBigInteger((BigInteger) any); + } else if (any instanceof Boolean){ + encodeAtom((Boolean) any); + } else if (any instanceof BertAtom) { + encodeAtom((BertAtom) any); + } else if (any instanceof String){ + encodeString((String) any); + } else if (any instanceof byte[]) { + encodeBinary((byte[]) any); + } else if (any instanceof BertTuple) { + encodeTuple((BertTuple) any); + } else if (any instanceof List) { + encodeList((List) any); + } else if (any instanceof Map) { + encodeMap((Map) any); + } else if (any.getClass().isArray()){ + encodeArray(any); + } + } + + private void encodeByte(Byte i) { + buffer.put(SMALL_INTEGER_EXT); + putUnsignedByte(i); + } + + private void encodeInteger(Integer i) { + if (SMALL_INTEGER_EXT_MIN_VAL <= i && i <= SMALL_INTEGER_EXT_MAX_VAL) { + encodeByte(i.byteValue()); + }else{ + buffer.put(INTEGER_EXT); + buffer.putInt(i); + } + } + + @SuppressWarnings("DefaultLocale, MalformedFormatString") + private void encodeDouble(Double d){ + switch (minorVersion){ + case OLD: + buffer.put(FLOAT_EXT); + String s = String.format("%0$-31.20e", d).replace(' ', '\0'); + buffer.put(s.getBytes(utf8Charset)); + break; + case NEW: + buffer.put(NEW_FLOAT_EXT); + buffer.putDouble(d); + break; + } + } + + private void encodeLong(Long l) { + if (Integer.MIN_VALUE <= l && l <= Integer.MAX_VALUE) { + encodeInteger(l.intValue()); + return; + } + + encodeBigInteger(BigInteger.valueOf(l)); + } + + private void encodeBigInteger(BigInteger b){ + byte[] bytes = b.toByteArray(); + + if (bytes.length <= SMALL_INTEGER_EXT_MAX_VAL){ + buffer.put(SMALL_BIG_EXT); + putUnsignedByte(bytes.length); + } else { + buffer.put(LARGE_BIG_EXT); + putUnsignedInt(bytes.length); + } + + buffer.put((byte) ((b.signum() >= 0) ? 0 : 1)); + for (int i = bytes.length; i > 0; i--){ + buffer.put(bytes[i - 1]); + } + } + + private void encodeAtom(Boolean b) { + encodeAtom(b.toString()); + } + + private void encodeAtom(BertAtom atom) { + encodeAtom(atom.get()); + } + + private void encodeAtom(String s) { + if (s.length() <= SMALL_INTEGER_EXT_MAX_VAL){ + buffer.put(SMALL_ATOM_EXT); + putUnsignedByte(s.length()); + } else { + buffer.put(ATOM_EXT); + putUnsignedShort(s.length()); + } + + buffer.put(s.getBytes(utf8Charset)); + } + + private void encodeString(String s) { + if (encodeStringAsBinary){ + encodeBinary(s.getBytes(utf8Charset)); + return; + } + + if (s.length() <= STRING_EXT_MAX_VAL){ + buffer.put(STRING_EXT); + putUnsignedShort(s.length()); + buffer.put(s.getBytes(utf8Charset)); + } else { + encodeArray(s.getBytes(utf8Charset)); + } + } + + private void encodeBinary(byte[] array){ + buffer.put(BINARY_EXT); + putUnsignedInt(array.length); + buffer.put(array); + } + + private void encodeNull(){ + buffer.put(NIL_EXT); + } + + private void encodeTuple(BertTuple tuple){ + + if (tuple.size() <= SMALL_INTEGER_EXT_MAX_VAL){ + buffer.put(SMALL_TUPLE_EXT); + putUnsignedByte(tuple.size()); + } else { + buffer.put(LARGE_TUPLE_EXT); + putUnsignedInt(tuple.size()); + } + + for(Object o: tuple){ + encode(o); + } + } + + private void encodeList(List list){ + + buffer.put(LIST_EXT); + + putUnsignedInt(list.size()); + for(Object o: list){ + encode(o); + } + encodeNull(); + } + + private void encodeMap(Map map) throws IllegalArgumentException{ + + if (encodeMapAsPropList) buffer.put(LIST_EXT); + else buffer.put(MAP_EXT); + + putUnsignedInt(map.size()); + + for (Map.Entry entry : map.entrySet()) { + + if (encodeMapAsPropList){ + buffer.put(SMALL_TUPLE_EXT); + putUnsignedByte(2); + } + + if (encodeMapKeysAsAtom) { + encodeAtom(entry.getKey().toString()); + } else if (encodeMapKeysAsString) { + encodeString(entry.getKey().toString()); + } else { + encode(entry.getKey()); + } + + encode(entry.getValue()); + } + + if (encodeMapAsPropList) encodeNull(); + } + + private void encodeArray(Object array){ + + buffer.put(LIST_EXT); + + int elements = Array.getLength(array); + putUnsignedInt(elements); + for (int i = 0; i < elements; i++){ + encode(Array.get(array, i)); + } + + encodeNull(); + } + + private void putUnsignedByte(int i) { + buffer.put((byte) (i & 0xff)); + } + + private void putUnsignedShort(int i) { + buffer.putShort((short) (i & 0xffff)); + } + + private void putUnsignedInt(long l) { + buffer.putInt((int) (l & 0xffffffffL)); + } +} diff --git a/app/src/main/java/com/tecsynt/nynja/server/com/softwarejoint/bert/BertTuple.java b/app/src/main/java/com/tecsynt/nynja/server/com/softwarejoint/bert/BertTuple.java new file mode 100644 index 0000000000000000000000000000000000000000..ef4399175c95645d71bb2eac4db9bbe1c6999d96 --- /dev/null +++ b/app/src/main/java/com/tecsynt/nynja/server/com/softwarejoint/bert/BertTuple.java @@ -0,0 +1,10 @@ +package com.tecsynt.nynja.server.com.softwarejoint.bert; + +import java.util.ArrayList; + +public class BertTuple extends ArrayList { + + boolean isKV() { + return size() == 2; + } +} diff --git a/app/src/main/java/com/tecsynt/nynja/server/com/softwarejoint/bert/DistributionHeader.java b/app/src/main/java/com/tecsynt/nynja/server/com/softwarejoint/bert/DistributionHeader.java new file mode 100644 index 0000000000000000000000000000000000000000..e09f31a604d44b7c32640ee2b81a32056fbd73a5 --- /dev/null +++ b/app/src/main/java/com/tecsynt/nynja/server/com/softwarejoint/bert/DistributionHeader.java @@ -0,0 +1,39 @@ +package com.tecsynt.nynja.server.com.softwarejoint.bert; + +interface DistributionHeader { + + enum VERSION{ + OLD, + NEW + } + + byte MAGIC = (byte) 131; + + byte NIL_EXT = (byte) 106; + + int SMALL_INTEGER_EXT_MIN_VAL = 0; + int SMALL_INTEGER_EXT_MAX_VAL = 255; + byte SMALL_INTEGER_EXT = (byte) 97; //DND: byte + byte INTEGER_EXT = (byte) 98; + + int FLOAT_LENGTH = 31; + byte FLOAT_EXT = (byte) 99; + byte NEW_FLOAT_EXT = (byte) 70; + + byte SMALL_BIG_EXT = (byte) 110; + byte LARGE_BIG_EXT = (byte) 111; + + byte ATOM_EXT = (byte) 100; //DND: max len: 255 + byte SMALL_ATOM_EXT = (byte) 115; + + int STRING_EXT_MAX_VAL = 65535; + byte STRING_EXT = (byte) 107; //DND: max size: 65535 + byte LIST_EXT = (byte) 108; + + byte BINARY_EXT = (byte) 109; + + byte SMALL_TUPLE_EXT = (byte) 104; + byte LARGE_TUPLE_EXT = (byte) 105; + + byte MAP_EXT = (byte) 116; +} diff --git a/app/src/main/java/com/tecsynt/nynja/server/com/softwarejoint/bert/model/InitModel.java b/app/src/main/java/com/tecsynt/nynja/server/com/softwarejoint/bert/model/InitModel.java new file mode 100644 index 0000000000000000000000000000000000000000..0c0dc5cb436e9c8695eddef3a0eb70a4e75de325 --- /dev/null +++ b/app/src/main/java/com/tecsynt/nynja/server/com/softwarejoint/bert/model/InitModel.java @@ -0,0 +1,10 @@ +package com.tecsynt.nynja.server.com.softwarejoint.bert.model; + +public class InitModel extends ServerResponse{ + + private int vnode; + + public int getVnode() { + return vnode; + } +} diff --git a/app/src/main/java/com/tecsynt/nynja/server/com/softwarejoint/bert/model/ServerResponse.java b/app/src/main/java/com/tecsynt/nynja/server/com/softwarejoint/bert/model/ServerResponse.java new file mode 100644 index 0000000000000000000000000000000000000000..f851127e2d2ac10db7d575c4464b71dd6066b767 --- /dev/null +++ b/app/src/main/java/com/tecsynt/nynja/server/com/softwarejoint/bert/model/ServerResponse.java @@ -0,0 +1,62 @@ +package com.tecsynt.nynja.server.com.softwarejoint.bert.model; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.util.Log; + + +import com.tecsynt.nynja.server.com.softwarejoint.bert.BertAtom; +import com.tecsynt.nynja.server.com.softwarejoint.bert.BertTuple; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +@SuppressWarnings("WeakerAccess") +public class ServerResponse { + + private BertAtom vnode_max; + + public BertAtom getVnode_max() { + return vnode_max; + } + + + public void deserialize(BertTuple response) { + List fields = getFieldsUpTo(this.getClass(), null); + if (fields != null && !fields.isEmpty()) { + Collections.reverse(fields); + for (int i = 0; i < fields.size(); i++) { + try { + Field field = fields.get(i); + field.setAccessible(true); + field.set(this, response.get(i)); + } catch (Exception e) { + e.printStackTrace(); + } + + } + } + } + + @SuppressWarnings("ConstantConditions") + private static List getFieldsUpTo(@NonNull Class type, @Nullable Class exclusiveParent) { + try { + + List result = new ArrayList<>(); + result.addAll(Arrays.asList(type.getDeclaredFields())); + + Class parentClass = type.getSuperclass(); + if (parentClass != null && parentClass != Object.class) { + List parentClassFields = getFieldsUpTo(parentClass, exclusiveParent); + result.addAll(parentClassFields); + } + return result; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/app/src/main/java/com/tecsynt/nynja/ui/activities/SplashActivity.java b/app/src/main/java/com/tecsynt/nynja/ui/activities/SplashActivity.java index e6526b6d08ac21622855228ee68c9b190dc9ca5e..07205b275d16b6aaa9b19c770994968682257f59 100644 --- a/app/src/main/java/com/tecsynt/nynja/ui/activities/SplashActivity.java +++ b/app/src/main/java/com/tecsynt/nynja/ui/activities/SplashActivity.java @@ -6,6 +6,7 @@ import android.os.Handler; import android.support.annotation.Nullable; import com.tecsynt.nynja.R; +import com.tecsynt.nynja.server.PahoService; import com.tecsynt.nynja.ui.base.BaseActivity; /** @@ -15,13 +16,16 @@ import com.tecsynt.nynja.ui.base.BaseActivity; public class SplashActivity extends BaseActivity { - @Override protected void onCreate(@Nullable Bundle savedInstanceState) { + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_splash); - new Handler().postDelayed(new Runnable() { - @Override public void run() { - startActivity(new Intent(SplashActivity.this, WelcomeActivity.class)); - } - }, 2000); + startServerService(); + new Handler().postDelayed(() -> startActivity(new Intent(SplashActivity.this, WelcomeActivity.class)), 2000); } + + private void startServerService() { + this.startService(PahoService.newInstance(this)); + } + } diff --git a/app/src/main/java/com/tecsynt/nynja/ui/base/BaseActivity.java b/app/src/main/java/com/tecsynt/nynja/ui/base/BaseActivity.java index bef19d1cd224583c5c567b6ccbd24fcd062b36e1..3224b8ae337741427b64ff0264d4ff84a4db6b31 100644 --- a/app/src/main/java/com/tecsynt/nynja/ui/base/BaseActivity.java +++ b/app/src/main/java/com/tecsynt/nynja/ui/base/BaseActivity.java @@ -1,6 +1,7 @@ package com.tecsynt.nynja.ui.base; import android.os.Bundle; +import android.support.annotation.LayoutRes; import com.arellomobile.mvp.MvpAppCompatActivity; @@ -11,10 +12,11 @@ import butterknife.ButterKnife; * Email: duo.blood@gmail.com */ -public class BaseActivity extends MvpAppCompatActivity { +public abstract class BaseActivity extends MvpAppCompatActivity { - @Override protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + @Override + public void setContentView(@LayoutRes int layoutResID) { + super.setContentView(layoutResID); ButterKnife.bind(this); } -} +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_welcome.xml b/app/src/main/res/layout/activity_welcome.xml index ecb572b873c603af75915ee43ef6062890fbb2b9..7d8002f9f5d30c390078dface77e7aafa2edeb7e 100644 --- a/app/src/main/res/layout/activity_welcome.xml +++ b/app/src/main/res/layout/activity_welcome.xml @@ -37,6 +37,21 @@ android:layout_marginEnd="16dp" android:background="@drawable/bg_oval_btn_next" app:srcCompat="@drawable/v_navigate_next_red_24dp" - tools:ignore="ContentDescription"/> + tools:ignore="ContentDescription" /> + +