Skip to content

Commit

Permalink
Brief: first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
DadeKuma committed Mar 12, 2019
1 parent 2b5432a commit e229bbe
Show file tree
Hide file tree
Showing 20 changed files with 706 additions and 0 deletions.
1 change: 1 addition & 0 deletions droidstomplib/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
35 changes: 35 additions & 0 deletions droidstomplib/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
apply plugin: 'com.android.library'

android {
compileSdkVersion 28



defaultConfig {
minSdkVersion 16
targetSdkVersion 28
versionCode 1
versionName "1.0"

testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}

}

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])

implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.squareup.okhttp3:okhttp:3.12.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
21 changes: 21 additions & 0 deletions droidstomplib/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.github.dadekuma.droidstomplib;

import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;

import org.junit.Test;
import org.junit.runner.RunWith;

import static org.junit.Assert.*;

/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();

assertEquals("com.github.dadekuma.droidstomplib.test", appContext.getPackageName());
}
}
2 changes: 2 additions & 0 deletions droidstomplib/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.github.dadekuma.droidstomplib" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.github.dadekuma.droidstomplib.connection;

import com.github.dadekuma.droidstomplib.payload.HttpHeader;

import java.util.Collection;

public interface IConnectionProvider {
void connect(String stompEndpoint, Collection<HttpHeader> headers);
void send(String payload);
void setStompCallback(IStompCallback stompCallback);
boolean isConnected();
boolean isConnecting();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.github.dadekuma.droidstomplib.connection;

public interface IStompCallback {
void onConnectionOpened();
void onConnectionClosed(int code, String reason);
void onResponseReceived(String response);
void onMessageReceived(String topic, Long subscriptionId, String message);
boolean isConnected();
boolean isConnecting();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.github.dadekuma.droidstomplib.connection;

import com.github.dadekuma.droidstomplib.payload.HttpHeader;

import java.util.Collection;

public interface IStompClient {
void setStompCallback(IStompCallback stompCallback);
void connect(String stompEndpoint);
void connect(String stompEndpoint, Collection<HttpHeader> headers);
void send(String stompDestination, String message);
void sendJson(String stompDestination, String jsonMessage);
void subscribe(String topic);
void unsubscribe(String topic);
void disconnect();
boolean isConnected();
boolean isConnecting();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package com.github.dadekuma.droidstomplib.connection;

import com.github.dadekuma.droidstomplib.payload.HttpHeader;

import java.util.Collection;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;


public class OkHttpConnectionProvider implements IConnectionProvider {
private OkHttpClient okHttpClient;
private WebSocket webSocket;
private IStompCallback stompCallback;

public OkHttpConnectionProvider() {
this(new OkHttpClient());
}

public OkHttpConnectionProvider(OkHttpClient okHttpClient) {
this.okHttpClient = okHttpClient;
}


@Override
public void connect(String stompEndpoint, Collection<HttpHeader> headers) {
Request.Builder requestBuilder = new Request.Builder().url(stompEndpoint);
//add all http headers that you need to the request.
for (HttpHeader h : headers) {
requestBuilder.addHeader(h.getName(), h.getValue());
}
Request request = requestBuilder.build();

webSocket = okHttpClient.newWebSocket(request, new WebSocketListener() {
@Override
public void onOpen(WebSocket webSocket, Response response) {
if(stompCallback == null) return;
stompCallback.onConnectionOpened();
}

@Override
public void onMessage(WebSocket webSocket, ByteString bytes) {
}

@Override
public void onClosed(WebSocket webSocket, int code, String reason) {
if(stompCallback == null) return;
stompCallback.onConnectionClosed(code, reason);
}

@Override
public void onMessage(WebSocket webSocket, String text) {
if(stompCallback == null) return;
stompCallback.onResponseReceived(text);
}
});
}

@Override
public void send(String payload) {
webSocket.send(payload);
}

@Override
public void setStompCallback(IStompCallback stompCallback) {
this.stompCallback = stompCallback;
}

@Override
public boolean isConnected() {
return stompCallback.isConnected();
}

@Override
public boolean isConnecting() {
return stompCallback.isConnecting();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.github.dadekuma.droidstomplib.connection;

import com.github.dadekuma.droidstomplib.enums.StompHeaderName;
import com.github.dadekuma.droidstomplib.payload.StompFrame;
import com.github.dadekuma.droidstomplib.payload.StompParser;

import java.util.Map;

public abstract class StompCallback implements IStompCallback{
private boolean isConnected, isConnecting;

@Override
public void onConnectionOpened() {
isConnecting = true;
}

@Override
public void onConnectionClosed(int code, String reason) {
isConnected = isConnecting = false;
}

@Override
public void onResponseReceived(String response) {
StompFrame stompFrame = StompParser.parse(response);
switch (stompFrame.getStompCommand()){
case CONNECTED:
isConnected = true;
break;
case MESSAGE:
handleSubscriptionMessage(stompFrame);
break;
}
}

private void handleSubscriptionMessage(StompFrame stompFrame){
Map<StompHeaderName, String> headers = stompFrame.getStompHeaders();
String topic = headers.get(StompHeaderName.DESTINATION);
long subscriptionId = Long.parseLong(headers.get(StompHeaderName.SUBSCRIPTION));
String body = stompFrame.getStompBody();
onMessageReceived(topic, subscriptionId, body);
}

@Override
public abstract void onMessageReceived(String topic, Long subscriptionId, String message);

@Override
public boolean isConnected() {
return isConnected;
}

@Override
public boolean isConnecting() {
return isConnecting;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package com.github.dadekuma.droidstomplib.connection;

import android.util.Log;

import com.github.dadekuma.droidstomplib.enums.StompCommandName;
import com.github.dadekuma.droidstomplib.enums.StompHeaderName;
import com.github.dadekuma.droidstomplib.payload.HttpHeader;
import com.github.dadekuma.droidstomplib.payload.StompFrame;

import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;

public class StompClient implements IStompClient {
private Map<String, Long> subscriptions;
private long subscriptionId;
private IConnectionProvider connectionProvider;

public StompClient() {
this(new OkHttpConnectionProvider());
}

public StompClient(IConnectionProvider connectionProvider) {
this.connectionProvider = connectionProvider;
subscriptions = new HashMap<>();
}

@Override
public void connect(String stompEndpoint) {
connect(stompEndpoint, new LinkedList<HttpHeader>());
}

@Override
public void connect(String stompEndpoint, Collection<HttpHeader> headers) {
connectionProvider.connect(stompEndpoint, headers);
StompFrame stompFrame = new StompFrame();
stompFrame.addStompCommand(StompCommandName.CONNECT)
.addStompHeader(StompHeaderName.ACCEPT_VERSION, "1.0,1.1,2.0")
.addStompHeader(StompHeaderName.HOST, "stomp.github.org");
connectionProvider.send(stompFrame.build());
}

@Override
public void send(String stompDestination, String message) {
StompFrame stompFrame = new StompFrame();
stompFrame.addStompCommand(StompCommandName.SEND)
.addStompHeader(StompHeaderName.DESTINATION, stompDestination)
.addStompHeader(StompHeaderName.CONTENT_TYPE, "text/plain")
.addBody(message);
connectionProvider.send(stompFrame.build());
}

@Override
public void sendJson(String stompDestination, String jsonMessage) {
StompFrame stompFrame = new StompFrame();
stompFrame.addStompCommand(StompCommandName.SEND)
.addStompHeader(StompHeaderName.DESTINATION, stompDestination)
.addStompHeader(StompHeaderName.CONTENT_TYPE, "application/json;charset=utf-8")
.addBody(jsonMessage);
connectionProvider.send(stompFrame.build());
}

@Override
public void subscribe(String topic) {
subscriptionId += 1;
StompFrame stompFrame = new StompFrame();
stompFrame.addStompCommand(StompCommandName.SUBSCRIBE)
.addStompHeader(StompHeaderName.ID, String.valueOf(subscriptionId))
.addStompHeader(StompHeaderName.DESTINATION, topic)
.addStompHeader(StompHeaderName.ACK, "auto");
connectionProvider.send(stompFrame.build());
subscriptions.put(topic, subscriptionId);
}

@Override
public void unsubscribe(String topic) {
if (!subscriptions.containsKey(topic)) {
Log.e("SUB_NOT_FOUND", "Subscription doesn't exist");
return;
}
Long unsubscribeId = subscriptions.get(topic);
StompFrame stompFrame = new StompFrame();
stompFrame.addStompCommand(StompCommandName.UNSUBSCRIBE)
.addStompHeader(StompHeaderName.ID, String.valueOf(unsubscribeId));
connectionProvider.send(stompFrame.build());
}

@Override
public void disconnect() {
unsubscribeAll();
StompFrame stompFrame = new StompFrame();
stompFrame.addStompCommand(StompCommandName.DISCONNECT)
.addStompHeader(StompHeaderName.RECEIPT, String.valueOf(subscriptionId));
connectionProvider.send(stompFrame.build());
}

public void unsubscribeAll() {
for (String topic : subscriptions.keySet()) {
unsubscribe(topic);
}
}

@Override
public void setStompCallback(IStompCallback stompCallback){
connectionProvider.setStompCallback(stompCallback);
}

@Override
public boolean isConnected() {
return connectionProvider.isConnected();
}

@Override
public boolean isConnecting() {
return connectionProvider.isConnecting();
}
}
Loading

0 comments on commit e229bbe

Please sign in to comment.