Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Anyone successful in implementing a WebSocket Server for Android?

I'm trying to implement both the WebSocket Client and the WebSocket Server on the same Android device. Basically I have two Android apps that need to communicate. I've implemented a couple of test apps using LocalSockets successfully, but the target Client side app is a web browser app so it can only use WebSockets.

I've tried the https://github.com/TooTallNate/Java-WebSocket implementation. I have the Client app running in the foreground and the Server app running in an Android Service in the background. Essentially, I've taken my LocalSocket implementations that works and replaced the LocalSockets with TooTallNate's WebSockets. It appears that the WebSocket Server is failing to start. The obvious symptom is that the Client side throws a NotYetConnectedException every time it tries to send something.

Another symptom is if I try to use WebSocketServer.run() instead of WebSocketServer.start() I get an IOException from ServerSocketChannel.open().

Any ideas are certainly welcome at this point. Thanks!

like image 883
jbelstner Avatar asked Nov 12 '22 05:11

jbelstner


1 Answers

A basic implementation is this:

public class ChatServer extends WebSocketServer
{
    private final String TAG = LogHelper.makeLogTag(ChatServer.class);

    private Map<String, WebSocket> clients = new ConcurrentHashMap<>();

    public ChatServer(int port)
    {
        super(new InetSocketAddress(port));
    }

    public ChatServer(InetSocketAddress address)
    {
        super(address);
    }

    @Override
    public void onOpen(WebSocket conn, ClientHandshake handshake) {
        String uniqueID = UUID.randomUUID().toString();
        clients.put(uniqueID, conn);

        conn.send(WrapHelper.regToJson(uniqueID));
        conn.send(WrapHelper.resToJson("Welcome to the server!"));


        broadcast((WrapHelper.resToJson("new connection: " + handshake.getResourceDescriptor()))); //This method sends a message to all clients connected
        LogHelper.e(TAG, conn.getRemoteSocketAddress().getAddress().getHostAddress() + " entered the room!");
    }

    @Override
    public void onClose(WebSocket conn, int code, String reason, boolean remote) {
        broadcast(WrapHelper.resToJson(conn + " has left the room!"));
        LogHelper.e(TAG, conn + " has left the room!");
    }

    @Override
    public void onMessage(WebSocket conn, String message) {
        Gson gson = new Gson();
        final Frame frame = gson.fromJson(message, Frame.class);
        if (frame != null) {
            LogHelper.e(TAG, "frame: " + frame);

            switch (frame.getCmd()) {
                case CMD_MSG:
                    broadcast(message);

                    break;

                case CMD_REG_USER:

                    break;
            }
        }
        LogHelper.e(TAG, conn + ": " + message);
    }

    @Override
    public void onMessage(WebSocket conn, ByteBuffer message) {
        broadcast(message.array());
        LogHelper.e(TAG, conn + ": " + message);
    }

    @Override
    public void onError(WebSocket conn, Exception ex)
    {
        ex.printStackTrace();
        if (conn != null) {
            // some errors like port binding failed may not be assignable to a specific websocket
        }
    }

    @Override
    public void onStart()
    {
        LogHelper.e(TAG, "Server started!");
        setConnectionLostTimeout(0);
        setConnectionLostTimeout(100);
    }
}

In this example you can see that we are overriding the abstract methods of the WebSocketServer class. You can create an interface to update your UI.

Then in your main activity you can use it like this:

@Override
protected void onCreate(Bundle savedInstanceState)
{
    ...

    ChatServer server = new ChatServer(DEFAULT_CHAT_PORT);
    server.start();

    ...
}

I have a full implementation of a chat sample here.

like image 87
Teocci Avatar answered Nov 14 '22 22:11

Teocci