Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which WebSocket library to use in Android app? [closed]

People also ask

Can we use WebSockets in Android?

The WebSocket protocol paved the way to a truly realtime web. At the time of writing this article, the Android SDK does not have native support for WebSockets. However, it relies on the Java Development Kit (JDK), which includes support for WebSockets as part of javax. websocket package.

Do mobile apps use WebSockets?

Definitely, a WebSocket web app will run on any HTML5-compliant browser, including mobile browsers such as Safari for iOS and Chrome for mobile.

What is WebSocket library?

websockets is a library for building WebSocket servers and clients in Python with a focus on correctness, simplicity, robustness, and performance. Built on top of asyncio , Python's standard asynchronous I/O framework, it provides an elegant coroutine-based API.


Some notes.

  • koush/AndroidAsync does not perform the closing handshake which is required by RFC 6455. See this for details.

  • Project Tyrus works on Android, but make sure that its license (CDDL 1.1 and GPL 2 with CPE) and its size (Reducing WebSocket client jar size with ProGuard) meet your requirements. Also note that Tyrus may throw an exception when a text size is large (it's probably a bug). See this for details.

  • Jetty: A 2-year-ago email thread in jetty-users mailing list says "We currently have no Android compatible Jetty 9 WebSocket client. There are plans to attempt to backport the Jetty WebSocket Client from JDK 7 to JDK 5/6 for android use, but its a lower priority than finishing our implementation of JSR-356 Java WebSocket API (javax.websocket)." Jetty's current document about its WebSocket Client API does not mention anything about Android.

  • codebutler/android-websocket does not perform the closing handshake which is required by RFC 6455 and may throw an exception on close. See this.

  • Atmosphere/wasync uses AsyncHttpClient/async-http-client as its WebSocket implementation. So, rather, AsyncHttpClient/async-http-client should be mentioned instead.

  • firebase/TubeSock does not verify Sec-WebSocket-Accept. This is a violation against RFC 6455. Also, TubeSock has a bug in building a text message. You will encounter the bug sooner or later if you use multi-byte UTF-8 characters for text messages. See Issue 3 in delight-im/Android-DDP for a long list about TubeSock problems.

Consideration Points

Consideration points in selecting a WebSocket client implementation written in Java:

  1. Compliance. Not a small number of implementations do not implement the closing handshake required by RFC 6455. (What happens if the closing handshake is not implemented? See this.)
  2. Required Java version. Java SE 5, 6, 7, 8 or Java EE? Works even on Android?
  3. Size. Some implementations have many dependencies.
  4. wss support.
  5. HTTP proxy support.
  6. wss over HTTP proxy support. See Figure 2 in How HTML5 Web Sockets Interact With Proxy Servers about what a WebSocket client library has to do to support wss over HTTP proxy.
  7. Flexibility on SSL configuration. SSLSocketFactory and SSLContext should be able to be utilized without unnecessary restrictions.
  8. Custom HTTP headers in the opening handshake, including Basic Authentication.
  9. Custom HTTP headers in HTTP proxy negotiation, including authentication at the proxy server.
  10. Capable of sending all the frame types (continuation, binary, text, close, ping and pong) or not. Most implementations do not provide developers with means to send fragmented frames and unsolicited pong frames manually.
  11. Listener interface to receive various WebSocket events. A poor interface makes developers frustrated. A rich interface helps developers write robust applications.
  12. Able to inquire WebSocket state or not. RFC 6455 defines CONNECTING, OPEN, CLOSING and CLOSED states, but few implementations maintain their internal state transition in the defined way.
  13. Able to set a timeout value for socket connection. (Equivalent to the second argument of Socket.connect(SocketAddress endpoint, int timeout) method)
  14. Able to access the underlying raw socket.
  15. Intuitive easy-to-use API or not.
  16. Well-documented or not.
  17. RFC 7692 (Compression Extensions for WebSocket) support (aka permessage-deflate).
  18. Redirection (3xx) support.
  19. Digest Authentication support.

nv-websocket-client covers all the above except the last two. In addition, one of its small but convenient features is to send ping/pong frames periodically. It can be achieved just by calling setPingInterval/setPongInterval methods (See JavaDoc).

Disclaimer: Takahiko Kawasaki is the author of nv-websocket-client.


Some other considerations:

Tyrus works on Android. However, the SSL libraries it uses in Android 5.0 are buggy and fail SSL handshakes. This is supposed to be fixed in newer versions of Android, but with the way that Android is not updated on many devices, this may be a problem for you.

Depending on how SSL is implemented for other websocket implementations, this may also be a problem.

AndroidAsync does not have this SSL issue. It does have other issues like not being able to set timeouts.


a) Add this file in gradle file

compile 'com.github.nkzawa:socket.io-client:0.3.0'

b) Add these lines in Application Activity:

    public class MyApplication extends Application {
     private Socket mSocket;
        {
            try {
               mSocket = IO.socket(Config.getBaseURL());

            } catch (URISyntaxException e) {
                throw new RuntimeException(e);
            }
        }

        public Socket getSocket() {
            return mSocket;
        }
}

c) Add this function to your activity, where you called WebSocket:

     private void websocketConnection() {
            //Get websocket from application
            MyApplication app = (MyApplication ) getApplication();
            mSocket = app.getSocket();
            mSocket.on(Socket.EVENT_CONNECT, onConnect);
            mSocket.on(Socket.EVENT_DISCONNECT, onDisconnect);
            mSocket.on(Socket.EVENT_CONNECT_ERROR, onConnectError);
            mSocket.on(Socket.EVENT_CONNECT_TIMEOUT, onConnectError);
            mSocket.on("messageFromServer", onNewLocation);
            mSocket.connect();
        } 


    private Emitter.Listener onConnect = new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            runOnUiThread(() -> {
                if (!isConnected) {

                    RequestSocket mRequestSocket = new RequestSocket();

                    mRequestSocket.setToken("anil_singhania");
                   /* your parameter */
                    mSocket.emit("messageFromClient", new Gson().toJson(mRequestSocket));
                    Log.i("Socket Data", new Gson().toJson(mRequestSocket));
                    isConnected = true;
                }
            });
        }
    };

    private Emitter.Listener onDisconnect = args -> runOnUiThread(() -> {
        isConnected = false;
       /* Toast.makeText(getApplicationContext(),
                R.string.disconnect, Toast.LENGTH_LONG).show();*/
    });

    private Emitter.Listener onConnectError = args -> runOnUiThread(() -> {
         /*   Toast.makeText(getApplicationContext(),
            R.string.error_connect, Toast.LENGTH_LONG).show()*/
    });

    private Emitter.Listener onNewLocation = new Emitter.Listener() {
        @Override
        public void call(final Object... args) {
            runOnUiThread(() -> {


            });
        }
    };