├── websockets
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ └── values
│ │ │ │ └── strings.xml
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ │ └── com
│ │ │ └── craftsman
│ │ │ └── websockets
│ │ │ ├── Ws.java
│ │ │ └── WsImpl.java
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── craftsman
│ │ │ └── websockets
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── craftsman
│ │ └── websockets
│ │ └── ExampleInstrumentedTest.java
├── libs
│ └── autobahn-0.5.0.jar
├── README.md
├── proguard-rules.pro
├── build.gradle
└── websockets.iml
└── README.md
/websockets/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/websockets/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | websockets
3 |
4 |
--------------------------------------------------------------------------------
/websockets/libs/autobahn-0.5.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/issotina/WebSocketAndroidClient/HEAD/websockets/libs/autobahn-0.5.0.jar
--------------------------------------------------------------------------------
/websockets/README.md:
--------------------------------------------------------------------------------
1 | Android webSocket client for [Ratchet Server](http://socketo.me/)
2 | This android library use autobahn-java https://github.com/crossbario/autobahn-java
3 |
4 | Installation
5 |
--------------------------------------------------------------------------------
/websockets/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/websockets/src/test/java/com/craftsman/websockets/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.craftsman.websockets;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/websockets/src/androidTest/java/com/craftsman/websockets/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.craftsman.websockets;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumentation test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.craftsman.websockets.test", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/websockets/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/geecko/Environnement/Android/sdk_2/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/websockets/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 27
5 | buildToolsVersion '27.0.3'
6 |
7 | defaultConfig {
8 | minSdkVersion 14
9 | targetSdkVersion 27
10 | versionCode 1
11 | versionName "1.0"
12 |
13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
14 |
15 | }
16 | buildTypes {
17 | release {
18 | minifyEnabled false
19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
20 | }
21 | }
22 | }
23 |
24 | dependencies {
25 | implementation fileTree(include: ['*.jar'], dir: 'libs')
26 | androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
27 | exclude group: 'com.android.support', module: 'support-annotations'
28 | })
29 | testImplementation 'junit:junit:4.12'
30 | implementation 'org.codehaus.jackson:jackson-mapper-asl:1.9.13'
31 | implementation 'com.google.code.gson:gson:2.8.1'
32 | implementation 'org.apache.commons:commons-lang3:3.6'
33 | }
34 |
--------------------------------------------------------------------------------
/websockets/src/main/java/com/craftsman/websockets/Ws.java:
--------------------------------------------------------------------------------
1 | package com.craftsman.websockets;
2 |
3 |
4 | import java.util.List;
5 |
6 | @SuppressWarnings("JavaDoc")
7 | public interface Ws {
8 |
9 | /**
10 | *
11 | * @return
12 | */
13 | Ws connect() throws Exception;
14 |
15 |
16 | /**
17 | *
18 | * @param channelPath
19 | * @param wsListner
20 | */
21 | Ws on(String channelPath, Class exceptedDataType, WsListner wsListner);
22 |
23 |
24 | /**
25 | *
26 | * @param channelPath
27 | * @param wsListner
28 | * @return
29 | */
30 | Ws on(String channelPath, WsListner wsListner);
31 |
32 | /**
33 | * @param channelPath
34 | * @return
35 | */
36 | Ws unsubscribe(String channelPath);
37 |
38 | Ws unsubscribe(List channelPath);
39 |
40 | /**
41 | *
42 | * @param text
43 | */
44 | void send(String text);
45 |
46 |
47 | /**
48 | *
49 | * @param binary
50 | */
51 | void send(byte[] binary);
52 |
53 |
54 | /**
55 | *
56 | * @param channelPath
57 | * @param o
58 | */
59 | void send(String channelPath, Object o);
60 |
61 |
62 | /**
63 | *
64 | */
65 | void end();
66 |
67 | /**
68 | *
69 | */
70 | interface WsListner {
71 |
72 | void onEvent(String eventUri, T data);
73 | }
74 |
75 |
76 | class Builder {
77 | public Builder(){
78 | }
79 |
80 | public WsImpl from(String websocketServerUri){
81 | return new WsImpl(websocketServerUri);
82 | }
83 | }
84 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # WebSocketAndroidClient
2 |
3 | [](https://jitpack.io/#geeckmc/WebSocketAndroidClient)
4 |
5 | #### Android webSocket client for [Ratchet Server](http://socketo.me/)
6 | Credit : This android library use [Autobahn-java](https://github.com/crossbario/autobahn-java)
7 |
8 | ## Installation
9 | ### 1 - Add it in your root build.gradle at the end of repositories:
10 | ```groovy
11 |
12 | allprojects {
13 | repositories {
14 | ...
15 | maven { url 'https://jitpack.io' }
16 | }
17 | }
18 | ```
19 | ### 2 - Add the dependency
20 | ```groovy
21 | dependencies {
22 | compile 'com.github.geeckmc:WebSocketAndroidClient:0.0.7'
23 | }
24 | ```
25 |
26 | ### 3 - Add packaging options
27 | ```groovy
28 | android
29 | {
30 | ...
31 | packagingOptions {
32 | exclude 'META-INF/LICENSE'
33 | exclude 'META-INF/ASL2.0'
34 | }
35 | }
36 | ```
37 |
38 | ## Usage
39 | ### 1 - Create an Web Socket Instance and start connection
40 |
41 | ```java
42 | Ws ws = new Ws.Builder().from( "ws://server_address");
43 | ws.connect();
44 | ```
45 |
46 | ### 2 - Subscribe to channel
47 |
48 | Basically get raw data
49 | ```java
50 | ws.on("path/to/channel", new Ws.WsListner() {
51 | @Override
52 | public void onEvent(String eventUri, Object data) {
53 | if(data != null) //your logic here
54 | }
55 | });
56 | ```
57 | #### OR
58 |
59 | Get parsed object from json response,
60 | for example to get User from channel do something like this
61 |
62 | ```java
63 |
64 | ws.on("path/to/channel", User.class, new Ws.WsListner() {
65 | @Override
66 | public void onEvent(String eventUri, User user) {
67 | if(user != null) Log.e(TAG,user.name);
68 | }
69 | });
70 | ```
71 | ### 2 - Send data to server
72 |
73 | ```java
74 | ws.send("Hello World");
75 | ```
76 | or send to specific channel
77 |
78 | ```java
79 | ws.send("path/to/channel","Hello Channel");
80 | ```
81 |
82 | ### 3 - Close Connection and remove listners
83 | ```java
84 | ws.end();
85 | ```
86 |
87 |
88 |
89 | License
90 | -------
91 |
92 | Licensed under the Apache License, Version 2.0 (the "License");
93 | you may not use this file except in compliance with the License.
94 | You may obtain a copy of the License at
95 |
96 | http://www.apache.org/licenses/LICENSE-2.0
97 |
98 | Unless required by applicable law or agreed to in writing, software
99 | distributed under the License is distributed on an "AS IS" BASIS,
100 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
101 | See the License for the specific language governing permissions and
102 | limitations under the License.
103 |
--------------------------------------------------------------------------------
/websockets/src/main/java/com/craftsman/websockets/WsImpl.java:
--------------------------------------------------------------------------------
1 | package com.craftsman.websockets;
2 |
3 | import android.os.Handler;
4 | import android.util.Log;
5 |
6 | import com.google.gson.Gson;
7 |
8 | import org.apache.commons.lang3.StringUtils;
9 |
10 | import java.util.ArrayList;
11 | import java.util.List;
12 |
13 | import de.tavendo.autobahn.Autobahn;
14 | import de.tavendo.autobahn.AutobahnConnection;
15 |
16 | @SuppressWarnings("unchecked")
17 | public class WsImpl implements Ws {
18 | private final String TAG = "Web Socket Impl";
19 | private final List subscriptions = new ArrayList<>();
20 | private Handler mainHandler = new Handler();
21 | private AutobahnConnection autobahnConnection = new AutobahnConnection();
22 | private String serverUrl;
23 | private Runnable handleSocketReconnection = new Runnable() {
24 | @Override
25 | public void run() {
26 | try {
27 | if (autobahnConnection != null && !autobahnConnection.isConnected())
28 | connect();
29 | } catch (Exception e) {
30 | e.printStackTrace();
31 | }
32 | }
33 | };
34 |
35 | WsImpl(String websocketServerUri) {
36 | serverUrl = websocketServerUri;
37 | }
38 |
39 | public void changeSocketURI(String host, String port) throws Exception {
40 |
41 | if (serverUrl != null && !serverUrl.isEmpty()) {
42 |
43 | if (autobahnConnection != null && autobahnConnection.isConnected()) {
44 | end();
45 | }
46 |
47 | String[] spliter = serverUrl.split(":");
48 | if (host != null && !host.isEmpty()) {
49 | spliter[1] = "//" + host;
50 | }
51 |
52 | if (port != null && !port.isEmpty()) {
53 | spliter[2] = port;
54 | }
55 |
56 | serverUrl = StringUtils.join(spliter, ":");
57 |
58 | connect();
59 | }
60 | }
61 |
62 | @Override
63 | public Ws connect() throws Exception {
64 | if(serverUrl == null || !serverUrl.startsWith("ws")){
65 | throw new Exception("Right server url is not provided");
66 | }
67 | autobahnConnection.connect(serverUrl, new Autobahn.SessionHandler() {
68 | @Override
69 | public void onOpen() {
70 | Log.i(TAG,"Connected");
71 |
72 | for (final Payload payload: subscriptions) {
73 | //setup listener for all subscribed channel
74 | if(payload == null || payload.channel == null || payload.channel.isEmpty()) continue;
75 | else if(payload.channel.startsWith("/")) payload.channel = payload.channel.substring(1);
76 | autobahnConnection.subscribe(payload.channel, Object.class, new Autobahn.EventHandler() {
77 | @Override
78 | public void onEvent(String s, Object o) {
79 | try {
80 | payload.listner.onEvent(s,
81 | (payload.objectType != null) ?
82 | new Gson().fromJson(o.toString(),payload.objectType)
83 | : o);
84 | }
85 | catch (Exception e){
86 | e.printStackTrace();
87 | }
88 | }
89 | });
90 | }
91 | }
92 | @Override
93 | public void onClose(int i, String s) {
94 | //force recnnection to web socket
95 | Log.e(TAG, "Disconnected; Code " + i);
96 |
97 | if (i == 1 || i == 3 || i == 2 || i == 4 || i == 5) {
98 | mainHandler.removeCallbacks(handleSocketReconnection);
99 | mainHandler.postDelayed(handleSocketReconnection, 15000);
100 | }
101 | }
102 | });
103 | return this;
104 | }
105 |
106 | @Override
107 | public Ws on(final String channelPath, final Class exceptedDataType, final WsListner wsListner) {
108 | subscriptions.add(new Payload<>(channelPath, exceptedDataType, wsListner));
109 |
110 | if (!autobahnConnection.isConnected()) {
111 | return this;
112 | }
113 | else {
114 | autobahnConnection.subscribe(channelPath, Object.class, new Autobahn.EventHandler() {
115 | @Override
116 | public void onEvent(String s, Object o) {
117 | wsListner.onEvent(s,new Gson().fromJson(o.toString(),exceptedDataType));
118 | }
119 | });
120 | }
121 |
122 | return this;
123 | }
124 |
125 |
126 | @Override
127 | public Ws on(String channelPath, final WsListner wsListner) {
128 | subscriptions.add(new Payload<>(channelPath, null, wsListner));
129 | if (!autobahnConnection.isConnected()) {
130 | return this;
131 | }
132 | else autobahnConnection.subscribe(channelPath, Object.class, new Autobahn.EventHandler() {
133 | @Override
134 | public void onEvent(String s, Object o) {
135 | wsListner.onEvent(s, o);
136 | }
137 | });
138 |
139 | return this;
140 | }
141 |
142 | @Override
143 | public Ws unsubscribe(String channelPath) {
144 | for (Payload payload : subscriptions) {
145 | if (StringUtils.equals(payload.channel, channelPath)) {
146 | if (autobahnConnection != null) {
147 | if (autobahnConnection.isConnected())
148 | autobahnConnection.unsubscribe(channelPath);
149 |
150 | subscriptions.remove(payload);
151 | }
152 | }
153 | }
154 | return this;
155 | }
156 |
157 | @Override
158 | public Ws unsubscribe(List channelPath) {
159 | for (String payload : channelPath) {
160 | unsubscribe(payload);
161 | }
162 | return this;
163 | }
164 |
165 | @Override
166 | public void send( String text) {
167 | if(autobahnConnection.isConnected())
168 | autobahnConnection.sendTextMessage(text);
169 | }
170 |
171 | @Override
172 | public void send( byte[] binary) {
173 | if(autobahnConnection.isConnected())
174 | autobahnConnection.sendBinaryMessage(binary);
175 | }
176 |
177 | @Override
178 | public void send(String channelPath, Object o) {
179 | if(autobahnConnection.isConnected())
180 | autobahnConnection.publish(channelPath,o);
181 | }
182 |
183 | @Override
184 | public void end() {
185 | if(autobahnConnection != null && autobahnConnection.isConnected()) {
186 | autobahnConnection.unsubscribe();
187 | autobahnConnection.disconnect();
188 | }
189 | }
190 |
191 | final private class Payload{
192 | private String channel;
193 | private Class objectType;
194 | private WsListner listner;
195 |
196 | Payload(String channel, Class objectType, WsListner listner) {
197 | this.channel = channel;
198 | this.objectType = objectType;
199 | this.listner = listner;
200 | }
201 | }
202 | }
--------------------------------------------------------------------------------
/websockets/websockets.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | generateDebugSources
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
--------------------------------------------------------------------------------