A quick guide to WebSocket communication in Android

WebSockets are an alternative to HTTP communication in Web Applications. They offer a long lived, bidirectional communication channel between client and server. Once established, the channel is kept open, offering a very fast connection with low latency and overhead.

HTTP is a very different protocol, and also a different way of communicate. HTTP is a request/response protocol: the server returns some data when the client requests it.

With WebSockets:

  • the server can send a message to the client without the client explicitly requesting something
  • the client and the server can talk to each other simultaneously
  • very little data overhead needs to be exchanged to send messages. This means a low latency communication.

WebSockets are great for real-time and long-lived communications. HTTP is great for occasional data exchange and interactions initiated by the client.

Always use the secure, encrypted protocol for WebSockets, wss://. ws:// refers to the unsafe WebSockets version (the http:// of WebSockets), and should be avoided for obvious reasons.

nv-websocket-client

Let's use Tornado as Server and nv-websocket-client as WebSocket client for Android.

We are going to update the AndroidManifest.xml file by adding the following user permissions

<uses-permission android:name="android.permission.INTERNET" />

Add nv-websocket-client dependencies to your project dependencies by adding the following lines in your build.gradle and syncing the project:

dependencies {
    ...
    compile 'com.neovisionaries:nv-websocket-client:2.4'
}

Following is a example of WebSocket client for Android.

public class MainActivity extends AppCompatActivity  {
    WebSocket ws = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Create a WebSocket factory and set 5000 milliseconds as a timeout
        // value for socket connection.
        WebSocketFactory factory = new WebSocketFactory().setConnectionTimeout(5000);

        // Create a WebSocket. The timeout value set above is used.
        try {
            ws = factory.createSocket("ws://192.168.24.104:8888/ws/");

            ws.addListener(new WebSocketAdapter() {
                @Override
                public void onTextMessage(WebSocket websocket, String message) throws Exception {
                    Log.d("TAG", "onTextMessage: " + message);
                }
            });

            ws.connectAsynchronously();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (ws != null) {
            ws.disconnect();
            ws = null;
        }
    }

    public void sendMessage(View v) {
        if (ws.isOpen()) {
            ws.sendText("Message from Android!");
        }
    }
}

Result

android_audio_fortmats.png

Socket.IO-client Java

Socket.IO-client Java is the Socket.IO v1.x Client Library for Java, which is simply ported from the JavaScript client.

Create server as described here.

We are going to update the AndroidManifest.xml file by adding the following user permissions

<uses-permission android:name="android.permission.INTERNET" />

Add socket.io-client dependencies to your project dependencies by adding the following lines in your build.gradle and syncing the project:

dependencies {
    ...
    compile ('io.socket:socket.io-client:1.0.0') {
        // excluding org.json which is provided by Android
        exclude group: 'org.json', module: 'json'
    }
}

Following is a example of Socket.IO client for Android.

public class CropActivity extends AppCompatActivity  {
    private Socket socket = null;
    private Activity activity = CropActivity.this;

    private Emitter.Listener onConnectError = new Emitter.Listener() {
        @Override
        public void call(final Object... args) {
            Log.d("TAG", "onConnectError: " + args);
        }
    };

    private Emitter.Listener onDisconnect = new Emitter.Listener(){
        @Override
        public void call(final Object... args) {
            if (activity != null)
                activity.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            Log.d("TAG", "onDisconnect: " + args);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                });
        }
    };

    private Emitter.Listener onConnect = new Emitter.Listener() {
        @Override
        public void call(final Object... args) {
            Log.d("TAG", "onConnect: " + args);
        }
    };

    private Emitter.Listener newMessageListner = new Emitter.Listener() {
        @Override
        public void call(final Object... args) {
            Log.d("TAG", "newMessageListner: " + args);
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_crop);

        try {
            socket = IO.socket("http://192.168.24.104:8888");

            socket.on(Socket.EVENT_CONNECT, onConnect);
            socket.on(Socket.EVENT_DISCONNECT, onDisconnect);
            socket.on(Socket.EVENT_CONNECT_ERROR, onConnectError);
            socket.on("newMessage", newMessageListner);
            socket.connect();    //Connect socket to server
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (socket != null) {
            socket.disconnect();
            socket = null;
        }
    }

    public void sendMessage(View v) {
        if (socket.connected()) {
            socket.emit("newMessage","Message from Android!");
        }
    }
}

Useful tutorials

Useful libs

  • Socket class implements client sockets
  • ServerSocket class implements server sockets. A server socket waits for requests to come in over the network.
  • Autobahn|Java is a client library providing WAMP on Java 8 (Netty) and Android, plus (secure) WebSocket for Android.