Giter Site home page Giter Site logo

crossbario / autobahn-java Goto Github PK

View Code? Open in Web Editor NEW
1.5K 98.0 426.0 5.21 MB

WebSocket & WAMP in Java for Android and Java 8

Home Page: https://crossbar.io/autobahn

License: MIT License

Java 97.03% Makefile 0.57% Python 1.55% Shell 0.85%
java android java8 network websocket real-time wamp rpc pubsub autobahn

autobahn-java's Introduction

Autobahn|Java

Client library providing WAMP on Java 8 (Netty) and Android, plus (secure) WebSocket for Android.

Docker Hub Travis Docs


Autobahn|Java is a subproject of the Autobahn project and provides open-source client implementations for

running on Android and Netty/Java8/JVM.

The WebSocket layer is using a callback based user API, and is specifically written for Android. Eg it does not run any network stuff on the main (UI) thread.

The WAMP layer is using Java 8 CompletableFuture for WAMP actions (call, register, publish and subscribe) and the Observer pattern for WAMP session, subscription and registration lifecycle events.

The library is MIT licensed, maintained by the Crossbar.io Project, tested using the AutobahnTestsuite and published as a JAR to Maven and as a Docker toolchain image to Dockerhub.


Download

Grab via Maven:

<dependency>
    <groupId>io.crossbar.autobahn</groupId>
    <artifactId>autobahn-android</artifactId>
    <version>21.7.1</version>
</dependency>

Gradle:

dependencies {
    implementation 'io.crossbar.autobahn:autobahn-android:21.7.1'
}

For non-android systems use artifactID autobahn-java or just Download the latest JAR

Getting Started

The demo clients are easy to run, you only need make and docker installed to get things rolling.

$ make crossbar # Starts crossbar in a docker container
$ make python # Starts a python based WAMP components that provides calls for the Java demo client

and finally

$ make java # Starts the java (Netty) based demo client that performs WAMP actions

Show me some code

The code in demo-gallery contains some examples on how to use the autobahn library, it also contains convenience methods to use. Below is a basic set of code examples showing all 4 WAMP actions.

Subscribe to a topic

public void demonstrateSubscribe(Session session, SessionDetails details) {
    // Subscribe to topic to receive its events.
    CompletableFuture<Subscription> subFuture = session.subscribe("com.myapp.hello",
            this::onEvent);
    subFuture.whenComplete((subscription, throwable) -> {
        if (throwable == null) {
            // We have successfully subscribed.
            System.out.println("Subscribed to topic " + subscription.topic);
        } else {
            // Something went bad.
            throwable.printStackTrace();
        }
    });
}

private void onEvent(List<Object> args, Map<String, Object> kwargs, EventDetails details) {
    System.out.println(String.format("Got event: %s", args.get(0)));
}

Since we are only accessing args in onEvent(), we could simplify it like:

private void onEvent(List<Object> args) {
    System.out.println(String.format("Got event: %s", args.get(0)));
}

Publish to a topic

public void demonstratePublish(Session session, SessionDetails details) {
    // Publish to a topic that takes a single arguments
    List<Object> args = Arrays.asList("Hello World!", 900, "UNIQUE");
    CompletableFuture<Publication> pubFuture = session.publish("com.myapp.hello", args);
    pubFuture.thenAccept(publication -> System.out.println("Published successfully"));
    // Shows we can separate out exception handling
    pubFuture.exceptionally(throwable -> {
        throwable.printStackTrace();
        return null;
    });
}

A simpler call would look like:

public void demonstratePublish(Session session, SessionDetails details) {
    CompletableFuture<Publication> pubFuture = session.publish("com.myapp.hello", "Hi!");
    ...
}

Register a procedure

public void demonstrateRegister(Session session, SessionDetails details) {
    // Register a procedure.
    CompletableFuture<Registration> regFuture = session.register("com.myapp.add2", this::add2);
    regFuture.thenAccept(registration ->
            System.out.println("Successfully registered procedure: " + registration.procedure));
}

private CompletableFuture<InvocationResult> add2(
        List<Object> args, Map<String, Object> kwargs, InvocationDetails details) {
    int res = (int) args.get(0) + (int) args.get(1);
    List<Object> arr = new ArrayList<>();
    arr.add(res);
    return CompletableFuture.completedFuture(new InvocationResult(arr));
}

A very precise add2 may look like:

private List<Object> add2(List<Integer> args, InvocationDetails details) {
    int res = args.get(0) + args.get(1);
    return Arrays.asList(res, details.session.getID(), "Java");
}

Call a procedure

public void demonstrateCall(Session session, SessionDetails details) {
    // Call a remote procedure.
    CompletableFuture<CallResult> callFuture = session.call("com.myapp.add2", 10, 20);
    callFuture.thenAccept(callResult ->
            System.out.println(String.format("Call result: %s", callResult.results.get(0))));
}

Calling procedure with variable data type parameters

public void demonstrateCall(Session session, SessionDetails details) {
    // Call a remote procedure.
    byte[] var1 = new byte[20];
    String var2 = "A sample text";
    int var3 = 99;
    List<Object> args = new ArrayList<>();
    args.add(var1);
    args.add(var2);
    args.add(var3);
    CompletableFuture<CallResult> callFuture = session.call("com.myapp.myproc", args);
    callFuture.thenAccept(callResult ->
            System.out.println(String.format("Call result: %s", callResult.results.get(0))));
}

Connecting the dots

public void main() {
    // Create a session object
    Session session = new Session();
    // Add all onJoin listeners
    session.addOnJoinListener(this::demonstrateSubscribe);
    session.addOnJoinListener(this::demonstratePublish);
    session.addOnJoinListener(this::demonstrateCall);
    session.addOnJoinListener(this::demonstrateRegister);

    // finally, provide everything to a Client and connect
    Client client = new Client(session, url, realm);
    CompletableFuture<ExitInfo> exitInfoCompletableFuture = client.connect();
}

Authentication

Authentication is simple, we just need to create an object of the desired authenticator and pass that to the Client

Ticket Auth

public void main() {
    ...
    IAuthenticator authenticator = new TicketAuth(authid, ticket);
    Client client = new Client(session, url, realm, authenticator);
    CompletableFuture<ExitInfo> exitInfoCompletableFuture = client.connect();
}

Challenge Response Auth

public void main() {
    ...
    IAuthenticator authenticator = new ChallengeResponseAuth(authid, secret);
    Client client = new Client(session, url, realm, authenticator);
    CompletableFuture<ExitInfo> exitInfoCompletableFuture = client.connect();
}

Cryptosign Auth

public void main() {
    ...
    IAuthenticator authenticator = new CryptosignAuth(authid, privkey, pubkey);
    Client client = new Client(session, url, realm, authenticator);
    CompletableFuture<ExitInfo> exitInfoCompletableFuture = client.connect();
}

You can also provide a list of Authenticators

public void main() {
    ...
    List<IAuthenticator> authenticators = new ArrayList<>();
    authenticators.add(new TicketAuth(authid, ticket));
    authenticators.add(new CryptosignAuth(authid, privkey, pubkey));
    Client client = new Client(session, url, realm, authenticators);
    CompletableFuture<ExitInfo> exitInfoCompletableFuture = client.connect();
}

Autobahn also supports POJOs

Here is how to call a remote procedure that returns a list of Person POJOs

// Call a remote procedure that returns a Person with id 1
CompletableFuture<Person> callFuture = mSession.call("com.example.get_person", 1);
callFuture.whenCompleteAsync((person, throwable) -> {
    if (throwable != null) {
        // handle error
    } else {
        // success!
        // do something with person
    }
}, mExecutor);
// call a remote procedure that returns a List<Person>
CompletableFuture<List<Person>> callFuture = mSession.call(
        // remote procedure to call
        "com.example.get_persons_by_department",

        // positional call arguments
        new ArrayList<Object>() {List.of("department-7")},

        // call return type
        new TypeReference<List<Person>>() {}
);

callFuture.whenCompleteAsync((persons, throwable) -> {
    if (throwable != null) {
        // handle error
    } else {
        // success!
        for (Person person: persons) {
            // do something with person
        }
    }
}, mExecutor);

Also register a procedure that returns a Person

private Person get_person() {
    return new Person("john", "doe", "hr");
}

private void main() {
    CompletableFuture<Registration> regFuture = session.register(
            "io.crossbar.example.get_person", this::get_person);
    regFuture.whenComplete((registration, throwable) -> {
        System.out.println(String.format(
                "Registered procedure %s", registration.procedure));
    });
}

WebSocket on Android

Echo example

WebSocketConnection connection = new WebSocketConnection();
connection.connect("wss://echo.websocket.org", new WebSocketConnectionHandler() {
    @Override
    public void onConnect(ConnectionResponse response) {
        System.out.println("Connected to server");
    }

    @Override
    public void onOpen() {
        connection.sendMessage("Echo with Autobahn");
    }

    @Override
    public void onClose(int code, String reason) {
        System.out.println("Connection closed");
    }

    @Override
    public void onMessage(String payload) {
        System.out.println("Received message: " + payload);
        connection.sendMessage(payload);
    }
});

Building from source

Building Autobahn is pretty simple

Android build

For Android, we recommend to use Android Studio. Just import the project in Android Studio, it will tell you if there are any missing dependencies, install them and then just build the project from Build > Rebuild Project and you will have the aar artifact in autobahn/build/outputs/aar/

Netty build

To produce a build for non-android systems make sure you have docker and make installed then just use run below command on the root directory of the project

make build_autobahn

and that will output the jar file in autobahn/build/libs/.

Get in touch

Get in touch by joining our forum.


Version 1

Version 1 of this library is still in the repo here, but is no longer maintained.

Version 1 only supported non-secure WebSocket on Android and only supported WAMP v1.

Both of these issues are fixed in the (current) version of Autobahn|Java.


autobahn-java's People

Contributors

0xflotus avatar almozavr avatar chrismeyersfsu avatar cyrushine avatar darkl avatar fhriley avatar filipmaelbrancke avatar goeddea avatar hetzge avatar i-taozi avatar magnux avatar mrtnmch avatar murph avatar muzzammilshahid avatar noman720 avatar oberstet avatar om26er avatar ottoallmendinger avatar pavelvic avatar ralscha avatar william-ferguson-au avatar zerodivisi0n avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

autobahn-java's Issues

automate JAR creation

manual creation of the library JAR is somewhat annoying / error prone.

we need a script that when run builds and packages a JAR

The script should run on Windows and have no, or only reasonable dependencies.

reconnect issue

Reconnect successfully after CLOSE_CONNECTION_LOST, although I did subscribe, still can't receive topic

Multiple Endpoints on a Single Connection

First, congratulations for the project! It's a fantastic initiative!
I would like to ask you some questions about it:

  1. Is there a way to create a single WebSocket connection and send messages to multiple endpoints on the server? I saw that there are examples of this using RPC, but I would only use WebSocket. I would like something like SocksJs with STOMP:

    var ws = new SockJS(url);
    var client = Stomp.over(ws);
    client.connect(headers, connectCallback);
    client.send("/queue/test", {priority: 9}, "Hello, STOMP");

  2. The WSS protocol is fully supported by Android Autobahn?

  3. Is there any particular reason for using the Jackson 1.X? It's what I use version 2.x and I'm thinking of changing my fork of the autobahn for this version.

Already, thanks!

onclose not called if network is disconnected

in android 4.0 is plugged and lost connection to the socket does not try to reconnect or notifies the OnClose.... also the isConnected returns true, the ee sendTextMessage does not send the Feedback but also does not return any error .... some solution? how can I test connectivity from socket?

apparently on androd 4.2.2 and 2.3.7 works, so the connection is lost the authobehn notifies the onClose

thanks

How to add path and headers

How I can add path to url like this:
final String wsuri = "ws://localhost/room/12/";
and headers like this:
List extraHeaders = Arrays.asList(
new BasicNameValuePair("Authorization", "Token "+token)
);

Sending "," in subprotocols even if there is only one string.

Hello I've been trying to implement WebSocket client side which needed to send string "text-stream" as sub-protocol in handshake key. But WebSocketWriter send "text-stream," So I suggest to add in the method sendClientHandshake()

if (i != message.mSubprotocols.length - 1) {
mBuffer.write(", ");
}

to add comma only for separate strings.

Expose Jackson features to control AutoDetect

Some classes in 3rd party library I use deviate from the JavaBeans convention that Jackson expects by default.
AutobahnAndroid currently doesn't export the corresponding features in Jackson to control this, which makes the whole very cumbersome.

http://wiki.fasterxml.com/JacksonFeatureAutoDetect
http://www.cowtowncoder.com/blog/archives/2011/02/entry_443.html
http://www.cowtowncoder.com/blog/archives/2011/03/entry_448.html

A great solution would be to expose ObjectMapper.setVisibility.

server not accepting primitive parameters

first, great work on this library, its potentially very useful. I know that this is helping a lot of people.

So, I am working on an android app and trying to integrate it with websockets, the server is using signalR. I haven't seen any full fledged examples of signalR/A on android, and this might be an issue others might be experiencing too. It would be awesome if you could take a look at my code, and help me out with some obvious mistakes, and share this with others using signalR/A.

The problem I am running into is that the server is not accepting method calls with primitive data types, like ints, when I try to invoke the methods on the server from the client.

This is the method on the server I am trying to call from the client (android).

public void Vote(int id)
    {
        var result = hsPost.Vote(id, UserID, ShowingAnonymous, _db, _dbConnectionFactory);
        if (!result.Success)
        {
            Clients.Caller.error(result.Message);
            return;
        }
        var voteCount = result.Post.VoteCount + 1;
        var groups = new List<string>
        {
            String.Format("topic-{0}-feed", result.Post.PostTopicID),
            String.Format("topic-{0}-post-{1}", result.Post.PostTopicID, id)
        };
        Clients.OthersInGroups(groups).vote(id, UserID, voteCount);
        Clients.Caller.vote(id, UserID, voteCount);
    }

This is how I call the server method from the client.

hubProxy.invoke("Vote", ((int)id)).
                onError(new ErrorCallback() {
                    @Override
                    public void onError(Throwable throwable) {
                        StudioKit.debugLog("SignalR", "Error from Vote" + throwable.getMessage());
                    }
                }).
                done(new Action<Void>() {
                    @Override
                    public void run(Void aVoid) throws Exception {
                        StudioKit.debugLog("SignalR", "Successfully added vote");
                    }
                });
// id is the ID of the post I am voting for. Its a simple long, that I convert into an integer
// before sending out to the server

I get messages from the server, saying that
{"I":"6","E":"Cannot convert null to 'int' because it is a non-nullable value type"}, when clearly what I am sending is an integer. I have tried debugging it over and over again, it is sending the correct thing.

Also, another weird thing is that I have another place where I call the invoke method, that tries to join the groups on the server. It goes =>

groupName = new String[]{"topic-" + topicID,
            "topic-" + topicID
                    + "-user-" + mCurrentUser.getID(),
            "topic-" + topicID + "-feed"};
for (int j = 0; j < groupName.length; j++) {
        Log.d("SignalR method call => JoinGroup(" + groupName[j].toString() + ")");
        hubProxy.invoke("JoinGroup", groupName[j]);
}

And the add groups is pretty simple on the server side too.

public Task JoinGroup(string groupName)
    {
        return Groups.Add(Context.ConnectionId, groupName);
    }

In this case the server is able to recognize the data, and I am joining the groups as expected. Is there some obvious thing I am missing out or overlooking here.

NullPointerException in failConnection

02-13 11:14:02.896: E/AndroidRuntime(2400): FATAL EXCEPTION: main
02-13 11:14:02.896: E/AndroidRuntime(2400): java.lang.NullPointerException
02-13 11:14:02.896: E/AndroidRuntime(2400): at de.tavendo.autobahn.WebSocketConnection.failConnection(WebSocketConnection.java:157)
02-13 11:14:02.896: E/AndroidRuntime(2400): at de.tavendo.autobahn.WebSocketConnection.access$6(WebSocketConnection.java:136)
02-13 11:14:02.896: E/AndroidRuntime(2400): at de.tavendo.autobahn.WebSocketConnection$1.handleMessage(WebSocketConnection.java:347)
02-13 11:14:02.896: E/AndroidRuntime(2400): at android.os.Handler.dispatchMessage(Handler.java:99)
02-13 11:14:02.896: E/AndroidRuntime(2400): at android.os.Looper.loop(Looper.java:137)
02-13 11:14:02.896: E/AndroidRuntime(2400): at android.app.ActivityThread.main(ActivityThread.java:4424)
02-13 11:14:02.896: E/AndroidRuntime(2400): at java.lang.reflect.Method.invokeNative(Native Method)
02-13 11:14:02.896: E/AndroidRuntime(2400): at java.lang.reflect.Method.invoke(Method.java:511)
02-13 11:14:02.896: E/AndroidRuntime(2400): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
02-13 11:14:02.896: E/AndroidRuntime(2400): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
02-13 11:14:02.896: E/AndroidRuntime(2400): at dalvik.system.NativeStart.main(Native Method)

Server not getting client disconnected status

Hi,

I am using autobahn android client for WS connectivity.

It works flawlessly from client end to server and vice-versa is also good.

But issue comes when clients get disconnected due to network failure or Internet was forcefully disconnected. At this point of time android client gets to know that WS is disconnected but server is not.
If we check at server for WS socket it seem that sockets are still alive. But in real they are not.

Any help on this.

Implementation with socket io.

Hi,

I was trying to implement a chat application using this library, in server side it is socket.io.
Is there possible to receive the json object from the server when it passes a event.

IIS8 and AutobahnAndroid

Hi, I can't seem to get IIS8 work with AutobahnAndroid.
I have a simple websockets server set up on iis 8 and below JavaScript code works fine. But when I try with AutobahnAndroid Echo demo app I get error saying Websockets protocol error.

Here is the log

06-25 10:03:12.734: D/de.tavendo.autobahn.WebSocketReader(8505): created
06-25 10:03:12.734: D/de.tavendo.autobahn.WebSocketConnection(8505): WS reader created and started
06-25 10:03:12.734: D/de.tavendo.autobahn.WebSocketReader(8505): running
06-25 10:03:12.734: D/de.tavendo.autobahn.WebSocketWriter(8505): created
06-25 10:03:12.734: D/de.tavendo.autobahn.WebSocketConnection(8505): WS writer created and started
06-25 10:03:14.084: D/de.tavendo.autobahn.WebSocketConnection(8505): opening handshake received
06-25 10:03:14.084: D/de.tavendo.autobahn.WebSocketReader(8505): run() : WebSocketException (de.tavendo.autobahn.WebSocketException: RSV != 0 and no extension negotiated)
06-25 10:03:14.084: D/de.tavendo.autobahn.WebSocketReader(8505): ended
06-25 10:03:14.094: D/de.tavendo.autobahn.WebSocketConnection(8505): fail connection [code = 4, reason = WebSockets protocol violation
06-25 10:03:14.094: D/de.tavendo.autobahn.WebSocketReader(8505): quit
06-25 10:03:14.094: D/de.tavendo.autobahn.WebSocketWriter(8505): ended
06-25 10:03:14.114: D/de.tavendo.autobahn.WebSocketConnection(8505): worker threads stopped

here is my server code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Web;
using Microsoft.Web.WebSockets;
namespace WebSockets
{
public class TestWebSocketHandler : WebSocketHandler
{
private static WebSocketCollection clients = new WebSocketCollection();
private string name;

    public override void OnOpen()
    {
        this.name = this.WebSocketContext.QueryString["name"];
        clients.Add(this);
        clients.Broadcast(name + " has connected.");
    }

    public override void OnMessage(string message)
    {
        clients.Broadcast(string.Format("{0} said: {1}", name, message));
    }

    public override void OnClose()
    {
        clients.Remove(this);
        clients.Broadcast(string.Format("{0} has gone away.", name));
    }

}

}

Here is Javascript that connects and works with this server

<!doctype html>

<script src="Scripts/jquery-1.8.1.js" type="text/javascript"></script>
<script type="text/javascript">

    $(document).ready(function () {

        var name = prompt('what is your name?:');

        //Make sure you access http://localhost/index.htm as this hacky code works out the location of ws.ashx
        var url = 'ws://localhost/webSockets/ws.ashx?name=' + name;

        alert('Connecting to: ' + url);

        var ws = new WebSocket(url);

        ws.onopen = function () {
            $('#messages').prepend('Connected <br/>');
            $('#cmdSend').click(function () {
                ws.send($('#txtMessage').val());
                $('#txtMessage').val('');
            });
        };

        ws.onmessage = function (e) {
            $('#chatMessages').prepend(e.data + '<br/>');
        };

        $('#cmdLeave').click(function () {
            ws.close();
        });

        ws.onclose = function () {
            $('#chatMessages').prepend('Closed <br/>');
        };

        ws.onerror = function (e) {
            $('#chatMessages').prepend('Oops something went wront <br/>');
        };

    });

</script>

Wakelock Handling

Given that Autobahn doesn't require wakelocks, I was wondering what the right approach would be to prevent unwanted sleeps.

Could anyone provide some insight on how they solved the issues or they simply don't occur in real-world usage?
Thanks

WebSocketHandler

Hello,

I am trying to modify the code in order to adjust it though once I compile it, I can't find the WebSocketHandler class and 4-5 more classes.

Do you have any idea what am I missing ?

Thank you

Superflorous newline breaks communication with CherryPy/ws4py

Hex dump of TCP stream send by AutobahnAndroid:
00000000 47 45 54 20 2f 77 73 2f 65 63 68 6f 2f 20 48 54 GET /ws/ echo/ HT
00000010 54 50 2f 31 2e 31 0d 0a 48 6f 73 74 3a 20 31 39 TP/1.1.. Host: 19
00000020 32 2e 31 36 38 2e 30 2e 37 3a 39 38 38 34 0d 0a 2.168.0. 7:9884..
00000030 55 70 67 72 61 64 65 3a 20 57 65 62 53 6f 63 6b Upgrade: WebSock
00000040 65 74 0d 0a 43 6f 6e 6e 65 63 74 69 6f 6e 3a 20 et..Conn ection:
00000050 55 70 67 72 61 64 65 0d 0a 53 65 63 2d 57 65 62 Upgrade. .Sec-Web
00000060 53 6f 63 6b 65 74 2d 4b 65 79 3a 20 33 6a 4b 4d Socket-K ey: 3jKM
00000070 4d 56 32 66 47 31 57 78 57 54 65 45 73 53 6f 54 MV2fG1Wx WTeEsSoT
00000080 57 67 3d 3d 0a 0d 0a 53 65 63 2d 57 65 62 53 6f Wg==...S ec-WebSo
00000090 63 6b 65 74 2d 56 65 72 73 69 6f 6e 3a 20 31 33 cket-Ver sion: 13
000000A0 0d 0a 0d 0a ....

As you see, at 00000085 we have a superflorous newline (0x0a).

The code that writes this stuff is in AutobahnWriter.java.

  mBuffer.write("GET " + path + " HTTP/1.1");
  mBuffer.crlf();
  mBuffer.write("Host: " + message.mHost);
  mBuffer.crlf();
  mBuffer.write("Upgrade: WebSocket");
  mBuffer.crlf();
  mBuffer.write("Connection: Upgrade");
  mBuffer.crlf();
  mBuffer.write("Sec-WebSocket-Key: " + newHandshakeKey());
  mBuffer.crlf();
  if (message.mOrigin != null && !message.mOrigin.equals("")) {
     mBuffer.write("Origin: " + message.mOrigin);
     mBuffer.crlf();
  }
  mBuffer.write("Sec-WebSocket-Version: 13");
  mBuffer.crlf();
  mBuffer.crlf();

Apparently message.mOrigin has a extra newline at the end.

Suggested fix: Do not append the newline in the first place, or trim the origin.

WAMP subprotocol negotiation

recent versions of Autobahn WebSockets for Python expect proper subprotocol negotiation for WAMP.
implement that.

AutobahnAndroid: socket read returns -1

Hi there,
I seem to be having a problem with the AutobahnAndroid client library. Whenever the device goes to sleep (screen display is turning off), the socket on WebSocketReader eventually returns -1 and the client lost its connection with the server, and even the scheduled reconnection is also failed (3G connection is alive, the client also constantly pings the connection to the server to keep connection alive). Code snippet on WebSocketReader.java:

    do {
        // blocking read on socket
        int len = mSocket.read(mFrameBuffer); // ------> returns -1
        if (len > 0) {
           // process buffered data
           while (consumeData()) {
           }
        } else if (len < 0) {
           notify(new WebSocketMessage.ConnectionLost());
           mStopped = true;
        }
     } while (!mStopped);

Is this an issue? Or is it AutobahnAndroid simply cannot maintain connection while the device is in sleep mode?

Thank you guys.

WAMP Welcome message

recent versions of Autobahn WebSockets for Python send an initial WAMP Welcome message containing a unique, random session ID.
implement that.

Status "already connected", but the messages are not sent or received

This behavior has been repeatedly observed when the tablet or phone rest for a few hours with no action.

My log:
08-22 09:09:22.435: E/package.name.WS(23609): https://_.com/api/v1/system/notify
08-22 09:09:22.585: D/REQUEST GET(23609): {"headerFields":"{null=[HTTP/1.1 200 OK], Access-Control-Allow-Credentials=[true], Cache-Control=[no-cache], Connection=[keep-alive], Content-Length=[49], Content-Type=[text/plain], Date=[Fri, 22 Aug 2014 05:09:57 GMT], Server=[nginx], X-Android-Received-Millis=[1408684162592], X-Android-Response-Source=[NETWORK 200], X-Android-Selected-Transport=[http/1.1], X-Android-Sent-Millis=[1408684162568]}","respCode":200,"respContent":"{"notifyServerAddress":"ws://_
_.com:3050"}","respCookie":null,"requestUrl":"https://
__.com/api/v1/system/notify"}
08-22 09:09:22.585: E/package.name.WS(23609): respCode = 200
08-22 09:09:22.585: E/package.name.WS(23609): jsContent = {"notifyServerAddress":"ws://
***.com:3050"}
08-22 09:09:22.585: E/package.name.WS(23609): serverUrl = ws://__.com:3050
08-22 09:09:22.615: D/REQUEST GET(23609): {"headerFields":"{null=[HTTP/1.1 200 OK], Access-Control-Allow-Credentials=[true], Cache-Control=[no-cache], Connection=[keep-alive], Content-Length=[631], Content-Type=[text/plain], Date=[Fri, 22 Aug 2014 05:09:57 GMT], Server=[nginx], X-Android-Received-Millis=[1408684162627], X-Android-Response-Source=[NETWORK 200], X-Android-Selected-Transport=[http/1.1], X-Android-Sent-Millis=[1408684162570]}","respCode":200,"respContent":"{"objects":[{"_parent":"539f087a2b8fde9a6713c6b0","_parents":["52f8e742c2ac828f26000003","52f8e742c2ac828f26000004","534cdbb19714757905e11daf","539f087a2b8fde9a6713c6b0"],"_level":4,"_rev":0,"_title":"incomingData","_template":null,"_defaultChildrenTemplate":"539f0385980e419c67208013","_createdOn":1402931351560,"_createdBy":null,"_owner":"534cdbb19714757905e11dae","_alias":null,"_defaultChildrenAlias":null,"_workspace":{"name":"wSmarty","level":2,"origin":false,"originId":"539f0897fc0daaa167f53cc9"},"_file":null,"_subtreeRev":169,"_updatedOn":1402931351560,"_defaultChildrenWorkspace":null,"_id":"539f0898fc0daaa167f53ce8"}]}","respCookie":null,"requestUrl":"https://
__.com/api/v1/objects/534cdbb19714757905e11daf/children2?_levels=0,1,2&_title="incomingData""}
08-22 09:09:22.655: D/REQUEST GET(23609): {"headerFields":"{null=[HTTP/1.1 200 OK], Access-Control-Allow-Credentials=[true], Cache-Control=[no-cache], Connection=[keep-alive], Content-Length=[14], Content-Type=[text/plain], Date=[Fri, 22 Aug 2014 05:09:57 GMT], Server=[nginx], X-Android-Received-Millis=[1408684162659], X-Android-Response-Source=[NETWORK 200], X-Android-Selected-Transport=[http/1.1], X-Android-Sent-Millis=[1408684162632]}","respCode":200,"respContent":"{"objects":[]}","respCookie":null,"requestUrl":"https://
_****.com/api/v1/objects/539f0898fc0daaa167f53ce8/children2/?_fieldsinfo"}
08-22 09:09:22.715: E/package.name.WS(23609): already connected

Receive messages from the server does not work!
If we create a new connection again, the messages are received perfectly.

What can you do about it?

My code:

static void connect(final Context ctx, final String serverUrl) {

    try {
        WebSocketConnectionHandler wsHandler = new WebSocketConnectionHandler() {

            @Override
            public void onOpen() {
                Log.v(TAG, "Status: Connected to " + serverUrl);
                try {
                    sendMessage(ctx, authMessage(ctx, serverUrl));
                } catch(Exception e) { e.printStackTrace(); }
            }

            @Override
            public void onTextMessage(String payload) {
                Log.v(TAG, "Got echo: " + payload);
                if(payload != null) {
                    workWithAnswers(ctx, payload);
                }
            }

            @Override
            public void onClose(int code, String reason) {
                Log.v(TAG, "Connection lost. code = " + code + ", reason = " + reason);
                reconnectDelayed(ctx);
            }
        };

        conn.connect(serverUrl, wsHandler);

    } catch (WebSocketException e) {
        Log.e(TAG, e.getMessage());
    }
}

Thread WebSocketConnector remains active

After calling disconnect() thread WebSocketConnector remains active and dont disappear from application thread pool. Calling next connect() cause spawn new thread, so they are stacking in pool. Tested on Android 4.1.2

Public constructor for WebSocketMessage.Ping

Ping constructor should be public. It's necessary to send pings from the client code.

/// WebSockets ping to send or received.
public static class Ping extends Message {

   public byte[] mPayload;

   public Ping() {
     mPayload = null;
   }

   public Ping(byte[] payload) {
      mPayload = payload;
   }
}

decrease WS buffer sizes

currently, receive/send NIO buffers are 4MB ...

this was to check out performance limits, in particular while using the test suite client for Android.

it's unneccesarily large for normal use .. and breaks Android devices with limited heap

i.e. HTC Legend (2.2) (16Mb max heap)

make the default smaller, only configure larger sizes for test suite client ..

Jackson 2

It would be great if the Jackson 2 libraries were used.

I am integrating sclaoid and AutobahnAndroid but getting error

[info] Loading global plugins from /home/amit/.sbt/0.13/plugins
[info] Loading project definition from /home/amit/Downloads/hello-scaloid-sbt-master/project
[info] Set current project to hello-scaloid-sbt (in build file:/home/amit/Downloads/hello-scaloid-sbt-master/)
[info] Updating {file:/home/amit/Downloads/hello-scaloid-sbt-master/}hello-scaloid-sbt-master...
[info] Resolving jline#jline;2.12 ...
[info] Done updating.
[info] Processing resources
[warn] No main class detected
ProGuard, version 5.0
ProGuard is released under the GNU General Public License. You therefore
must ensure that programs that link to it (android, ...)
carry the GNU General Public License as well. Alternatively, you can
apply for an exception with the author of ProGuard.
Reading input...
Reading program jar /home/amit/Downloads/hello-scaloid-sbt-master/libs/weberknecht-0.1.1.jar
Reading program jar /home/amit/Downloads/hello-scaloid-sbt-master/libs/autobahn-android-0.5.2-SNAPSHOT.jar
Reading program jar /home/amit/.ivy2/cache/org.scala-lang/scala-library/jars/scala-library-2.11.4.jar
Reading program jar /home/amit/.ivy2/cache/org.scaloid/scaloid_2.11/jars/scaloid_2.11-3.6.1-10.jar
Reading program jar /home/amit/.ivy2/cache/org.scala-lang/scala-reflect/jars/scala-reflect-2.11.4.jar
Reading program jar /home/amit/.ivy2/cache/org.java-websocket/Java-WebSocket/jars/Java-WebSocket-1.3.0.jar
Reading program jar /home/amit/.ivy2/cache/net.sf.proguard/proguard-base/jars/proguard-base-5.1.jar
Reading program jar /home/amit/Downloads/hello-scaloid-sbt-master/bin/classes.jar
Reading library jar [/home/amit/Android/Sdk/platforms/android-19/android.jar]
Initializing...
Note: the configuration refers to the unknown class 'scaloid.example.HelloScaloid'
Warning: de.tavendo.autobahn.Wamp: can't find referenced class org.codehaus.jackson.type.TypeReference
Warning: de.tavendo.autobahn.Wamp: can't find referenced class org.codehaus.jackson.type.TypeReference
Warning: de.tavendo.autobahn.Wamp: can't find referenced class org.codehaus.jackson.type.TypeReference
Warning: de.tavendo.autobahn.Wamp: can't find referenced class org.codehaus.jackson.type.TypeReference
Warning: de.tavendo.autobahn.WampConnection: can't find referenced class org.codehaus.jackson.type.TypeReference
Warning: de.tavendo.autobahn.WampConnection: can't find referenced class org.codehaus.jackson.type.TypeReference
Warning: de.tavendo.autobahn.WampConnection: can't find referenced class org.codehaus.jackson.type.TypeReference
Warning: de.tavendo.autobahn.WampConnection: can't find referenced class org.codehaus.jackson.type.TypeReference
Warning: de.tavendo.autobahn.WampConnection: can't find referenced class org.codehaus.jackson.type.TypeReference
Warning: de.tavendo.autobahn.WampConnection: can't find referenced class org.codehaus.jackson.type.TypeReference
Warning: de.tavendo.autobahn.WampConnection: can't find referenced class org.codehaus.jackson.type.TypeReference
Warning: de.tavendo.autobahn.WampConnection: can't find referenced class org.codehaus.jackson.type.TypeReference
Warning: de.tavendo.autobahn.WampConnection$CallMeta: can't find referenced class org.codehaus.jackson.type.TypeReference
Warning: de.tavendo.autobahn.WampConnection$CallMeta: can't find referenced class org.codehaus.jackson.type.TypeReference
Warning: de.tavendo.autobahn.WampConnection$CallMeta: can't find referenced class org.codehaus.jackson.type.TypeReference
Warning: de.tavendo.autobahn.WampConnection$CallMeta: can't find referenced class org.codehaus.jackson.type.TypeReference
Warning: de.tavendo.autobahn.WampConnection$CallMeta: can't find referenced class org.codehaus.jackson.type.TypeReference
Warning: de.tavendo.autobahn.WampConnection$CallMeta: can't find referenced class org.codehaus.jackson.type.TypeReference
Warning: de.tavendo.autobahn.WampConnection$SubMeta: can't find referenced class org.codehaus.jackson.type.TypeReference
Warning: de.tavendo.autobahn.WampConnection$SubMeta: can't find referenced class org.codehaus.jackson.type.TypeReference
Warning: de.tavendo.autobahn.WampConnection$SubMeta: can't find referenced class org.codehaus.jackson.type.TypeReference
Warning: de.tavendo.autobahn.WampConnection$SubMeta: can't find referenced class org.codehaus.jackson.type.TypeReference
Warning: de.tavendo.autobahn.WampConnection$SubMeta: can't find referenced class org.codehaus.jackson.type.TypeReference
Warning: de.tavendo.autobahn.WampConnection$SubMeta: can't find referenced class org.codehaus.jackson.type.TypeReference
Warning: de.tavendo.autobahn.WampReader: can't find referenced class org.codehaus.jackson.map.ObjectMapper
Warning: de.tavendo.autobahn.WampReader: can't find referenced class org.codehaus.jackson.map.ObjectMapper
Warning: de.tavendo.autobahn.WampReader: can't find referenced class org.codehaus.jackson.map.DeserializationConfig$Feature
Warning: de.tavendo.autobahn.WampReader: can't find referenced class org.codehaus.jackson.map.ObjectMapper
Warning: de.tavendo.autobahn.WampReader: can't find referenced class org.codehaus.jackson.map.ObjectMapper
Warning: de.tavendo.autobahn.WampReader: can't find referenced class org.codehaus.jackson.JsonFactory
Warning: de.tavendo.autobahn.WampReader: can't find referenced class org.codehaus.jackson.JsonParser
Warning: de.tavendo.autobahn.WampReader: can't find referenced class org.codehaus.jackson.JsonToken
Warning: de.tavendo.autobahn.WampReader: can't find referenced class org.codehaus.jackson.JsonToken
Warning: de.tavendo.autobahn.WampReader: can't find referenced class org.codehaus.jackson.JsonParser
Warning: de.tavendo.autobahn.WampReader: can't find referenced class org.codehaus.jackson.JsonParser
Warning: de.tavendo.autobahn.WampReader: can't find referenced class org.codehaus.jackson.JsonParser
Warning: de.tavendo.autobahn.WampReader: can't find referenced class org.codehaus.jackson.JsonParser
Warning: de.tavendo.autobahn.WampReader: can't find referenced class org.codehaus.jackson.JsonToken
Warning: de.tavendo.autobahn.WampReader: can't find referenced class org.codehaus.jackson.JsonParser
Warning: de.tavendo.autobahn.WampReader: can't find referenced class org.codehaus.jackson.JsonParseException
Warning: de.tavendo.autobahn.WampReader: can't find referenced class org.codehaus.jackson.JsonParseException
Warning: de.tavendo.autobahn.WampReader: can't find referenced class org.codehaus.jackson.JsonParser
Warning: de.tavendo.autobahn.WampReader: can't find referenced class org.codehaus.jackson.JsonParseException
Warning: de.tavendo.autobahn.WampReader: can't find referenced class org.codehaus.jackson.map.DeserializationConfig$Feature
Warning: de.tavendo.autobahn.WampReader: can't find referenced class org.codehaus.jackson.JsonFactory
Warning: de.tavendo.autobahn.WampReader: can't find referenced class org.codehaus.jackson.JsonParser
Warning: de.tavendo.autobahn.WampReader: can't find referenced class org.codehaus.jackson.JsonToken
Warning: de.tavendo.autobahn.WampReader: can't find referenced class org.codehaus.jackson.map.DeserializationConfig
Warning: de.tavendo.autobahn.WampReader: can't find referenced class org.codehaus.jackson.map.ObjectMapper
Warning: de.tavendo.autobahn.WampReader: can't find referenced class org.codehaus.jackson.JsonFactory
Warning: de.tavendo.autobahn.WampReader: can't find referenced class org.codehaus.jackson.JsonParser
Warning: de.tavendo.autobahn.WampReader: can't find referenced class org.codehaus.jackson.JsonParseException
Warning: de.tavendo.autobahn.WampWriter: can't find referenced class org.codehaus.jackson.map.MappingJsonFactory
Warning: de.tavendo.autobahn.WampWriter: can't find referenced class org.codehaus.jackson.map.MappingJsonFactory
Warning: de.tavendo.autobahn.WampWriter: can't find referenced class org.codehaus.jackson.JsonFactory
Warning: de.tavendo.autobahn.WampWriter: can't find referenced class org.codehaus.jackson.JsonGenerator
Warning: de.tavendo.autobahn.WampWriter: can't find referenced class org.codehaus.jackson.JsonGenerator
Warning: de.tavendo.autobahn.WampWriter: can't find referenced class org.codehaus.jackson.JsonGenerator
Warning: de.tavendo.autobahn.WampWriter: can't find referenced class org.codehaus.jackson.JsonGenerator
Warning: de.tavendo.autobahn.WampWriter: can't find referenced class org.codehaus.jackson.JsonGenerator
Warning: de.tavendo.autobahn.WampWriter: can't find referenced class org.codehaus.jackson.JsonGenerationException
Warning: de.tavendo.autobahn.WampWriter: can't find referenced class org.codehaus.jackson.JsonGenerationException
Warning: de.tavendo.autobahn.WampWriter: can't find referenced class org.codehaus.jackson.map.JsonMappingException
Warning: de.tavendo.autobahn.WampWriter: can't find referenced class org.codehaus.jackson.map.JsonMappingException
Warning: de.tavendo.autobahn.WampWriter: can't find referenced class org.codehaus.jackson.JsonGenerator
Warning: de.tavendo.autobahn.WampWriter: can't find referenced class org.codehaus.jackson.JsonGenerator
Warning: de.tavendo.autobahn.WampWriter: can't find referenced class org.codehaus.jackson.JsonGenerator
Warning: de.tavendo.autobahn.WampWriter: can't find referenced class org.codehaus.jackson.JsonGenerationException
Warning: de.tavendo.autobahn.WampWriter: can't find referenced class org.codehaus.jackson.map.JsonMappingException
Warning: de.tavendo.autobahn.WampWriter: can't find referenced class org.codehaus.jackson.JsonFactory
Warning: de.tavendo.autobahn.WampWriter: can't find referenced class org.codehaus.jackson.JsonGenerator
Warning: de.tavendo.autobahn.WampWriter: can't find referenced class org.codehaus.jackson.JsonFactory
Warning: de.tavendo.autobahn.WampWriter: can't find referenced class org.codehaus.jackson.JsonGenerationException
Warning: de.tavendo.autobahn.WampWriter: can't find referenced class org.codehaus.jackson.map.JsonMappingException
Warning: de.tavendo.autobahn.WampWriter: can't find referenced class org.codehaus.jackson.JsonGenerator
Note: there were 1 references to unknown classes.
You should check your configuration for typos.
(http://proguard.sourceforge.net/manual/troubleshooting.html#unknownclass)
Warning: there were 75 unresolved references to classes or interfaces.
You may need to add missing library jars or update their versions.
If your code works fine without the missing classes, you can suppress
the warnings with '-dontwarn' options.
(http://proguard.sourceforge.net/manual/troubleshooting.html#unresolvedclass)
java.io.IOException: Please correct the above warnings first.
at proguard.Initializer.execute(Initializer.java:473)
at proguard.ProGuard.initialize(ProGuard.java:222)
at proguard.ProGuard.execute(ProGuard.java:97)
at android.Tasks$$anonfun$84.apply(tasks.scala:1260)
at android.Tasks$$anonfun$84.apply(tasks.scala:1233)
at scala.Function9$$anonfun$tupled$1.apply(Function9.scala:35)
at scala.Function9$$anonfun$tupled$1.apply(Function9.scala:34)
at scala.Function1$$anonfun$compose$1.apply(Function1.scala:47)
at sbt.$tilde$greater$$anonfun$$u2219$1.apply(TypeFunctions.scala:40)
at sbt.std.Transform$$anon$4.work(System.scala:63)
at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:226)
at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:226)
at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:17)
at sbt.Execute.work(Execute.scala:235)
at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:226)
at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:226)
at sbt.ConcurrentRestrictions$$anon$4$$anonfun$1.apply(ConcurrentRestrictions.scala:159)
at sbt.CompletionService$$anon$2.call(CompletionService.scala:28)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
error java.io.IOException: Please correct the above warnings first.
[error] Total time: 6 s, completed 23 Jan, 2015 11:18:16 AM

Change WebSocketHandler

I'm not sure if this is possible, but I would just like to change the WebSocketHandler that the websocket connection is using without having to disconnect and reconnect, is this at all possible?

Maintain and publish a proper changelog

Should there be a new version of the jar on the docs page? It downloaded 0.5.0.jar for me but I noticed the TAGS show up to 0.5.2

It might be nice to add a CHANGELOG.md file to show what has been added in each subsequent version of the client.

This is a really nice project and would love to help out in anyway.

gradle support

Please add support for gradle. I'm using IntelliJ/Android Studio and it would be cool, if I can use this library without self compiling.

Publish on Maven

To get the AutobahnAndroid artifact into the maven central repository you should use the facilities offered by oss.sonatype.org.
https://docs.sonatype.org/display/Repository/Sonatype+OSS+Maven+Repository+Usage+Guide

That should help you understand how to get the artifact and all associated metadata up to oss.sonatype.org, once you are happy with it, you can request that your artifacts be synced to Maven Central http://repo.maven.org/

FYI, sonatype.org is run by many Apache Maven committer and PMC members, they do a great job in helping out the open source community.

Automatic reestablishment of prefixes and subscriptions upon reconnect

I was just testing the automatic reconnection feature, but there seems to be an issue of using it together with a WampConnection.prefix call in the WampConnection.onOpen override.

m_acAutobahn.connect(...uri..., new Wamp.ConnectionHandler() {
  @Override
   public void onOpen() {
     m_acAutobahn.prefix("rpc", "http://example.com/main/rpc#");
     m_acAutobahn.call("rpc:call", Object.class, new Wamp.CallHandler() {
     }, ...ojbect...);

The code above causes a generic error response to the call (invalid WAMP message: missing array close or invalid additional args)

The code below works just fine upon an automatic reconnection

m_acAutobahn.connect(...uri..., new Wamp.ConnectionHandler() {
  @Override
   public void onOpen() {
     m_acAutobahn.call("http://example.com/main/rpc#call", Object.class, new Wamp.CallHandler() {
     }, ...ojbect...);

Exception: sending message to a Handler on a dead thread

10-07 10:53:27.659: W/MessageQueue(27516): Handler (de.tavendo.autobahn.WebSocketWriter) {42dbc630} sending message to a Handler on a dead thread
10-07 10:53:27.659: W/MessageQueue(27516): java.lang.RuntimeException: Handler (de.tavendo.autobahn.WebSocketWriter) {42dbc630} sending message to a Handler on a dead thread
10-07 10:53:27.659: W/MessageQueue(27516): at android.os.MessageQueue.enqueueMessage(MessageQueue.java:320)
10-07 10:53:27.659: W/MessageQueue(27516): at android.os.Handler.enqueueMessage(Handler.java:626)
10-07 10:53:27.659: W/MessageQueue(27516): at android.os.Handler.sendMessageAtTime(Handler.java:595)
10-07 10:53:27.659: W/MessageQueue(27516): at android.os.Handler.sendMessageDelayed(Handler.java:566)
10-07 10:53:27.659: W/MessageQueue(27516): at android.os.Handler.sendMessage(Handler.java:503)
10-07 10:53:27.659: W/MessageQueue(27516): at de.tavendo.autobahn.WebSocketWriter.forward(WebSocketWriter.java:102)
10-07 10:53:27.659: W/MessageQueue(27516): at de.tavendo.autobahn.WebSocketConnection.failConnection(WebSocketConnection.java:181)
10-07 10:53:27.659: W/MessageQueue(27516): at de.tavendo.autobahn.WebSocketConnection.access$1100(WebSocketConnection.java:34)
10-07 10:53:27.659: W/MessageQueue(27516): at de.tavendo.autobahn.WebSocketConnection$2.handleMessage(WebSocketConnection.java:453)
10-07 10:53:27.659: W/MessageQueue(27516): at android.os.Handler.dispatchMessage(Handler.java:102)
10-07 10:53:27.659: W/MessageQueue(27516): at android.os.Looper.loop(Looper.java:157)
10-07 10:53:27.659: W/MessageQueue(27516): at android.app.ActivityThread.main(ActivityThread.java:5356)
10-07 10:53:27.659: W/MessageQueue(27516): at java.lang.reflect.Method.invokeNative(Native Method)
10-07 10:53:27.659: W/MessageQueue(27516): at java.lang.reflect.Method.invoke(Method.java:515)
10-07 10:53:27.659: W/MessageQueue(27516): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
10-07 10:53:27.659: W/MessageQueue(27516): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
10-07 10:53:27.659: W/MessageQueue(27516): at dalvik.system.NativeStart.main(Native Method)

Not attempting connection to a Node-Websocket server

I've created an echo client using node-websocket (https://github.com/Worlize/WebSocket-Node) and am running it on a server of mine.

The Android client I've made follows the pattern here.

Yet, on neither the client nor the server is any life being shown. I've put breakpoints in the Android client and debugging, and onOpen() is never hit, so I guess it isn't trying - and on the server, it doesn't see any activity, not even failed activity. Are there any known issues to do with communicating with the server set up by node-websocket?

initial socket connect on background thread

socket readers/writers already live on long-lived background threads.

however, the initial socket connect is done on main / UI thread .. this breaks on Android 3+

solution: initial socket connect on short-lived, async background thread

Can't create jar

I want to build jar autobahn websocket for android. I downloaded it from trunk . Then unpacked, cd to autobahn dir, then ant jar but get error:

jar: [jar] Building MANIFEST-only jar: /home/dibo/programowanie/android/projects/tavendo-AutobahnAndroid-1e6b735/Autobahn/Autobahn.jar

BUILD SUCCESSFUL Total time: 0 seconds

And my Autobahn.jar file has only manifest file.

Regards

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.