¿Qué biblioteca de WebSocket usar en la aplicación de Android? [cerrado]

131

Quiero agregar un Servicio a mi aplicación de Android que se ejecuta en segundo plano con una conexión WebSocket (posiblemente durante varias horas o incluso días) y envía regularmente algunos datos a un servidor.

Ahora parece que hay un montón de bibliotecas WebSocket para Java, y no estoy seguro de cuál debo usar:

Además, hay una biblioteca de cliente socket.io nativa para Android:

  • nkzawa / socket.io-client.java Descripción de GitHub: Biblioteca de cliente Socket.IO con todas las funciones para Java, que es compatible con Socket.IO v1.0 y posterior.

Usar el cliente socket.io de Android sería útil para mí, porque de todos modos planeo usar nodejs / socket.io para la interfaz web. Pero el cliente nativo es bastante joven y tiene varios problemas abiertos. Y además de eso, tengo entendido que una aplicación de Android no tiene ningún beneficio de usar la biblioteca del cliente socket.io (además de ser compatible con el servidor socket.io 1.0), porque el soporte de WebSocket puede garantizarse en el lado del cliente .

Mis requisitos son los siguientes:

  • Compatibilidad con Android API 9 y superior
  • Posibilidad de conectarse a través de SSL
  • Mantenga la conexión durante mucho tiempo sin tener que mantener un wakelock permanente
  • Compatibilidad con una implementación de servidor websocket nodejs disponible o con socket.io

¿Alguna sugerencia sobre cuál es la biblioteca adecuada para estos requisitos?

radiografía
fuente
Quizás la atmósfera . Ver esta pregunta .
Basil Bourque
2
No soy experto en WebSocket ni Atmosphere. Solo sé que Atmosphere está muy usado, usado en muchos proyectos para funciones Push , incluido el soporte WebSocket. Mi única experiencia es indirecta, en la creación de aplicaciones web Vaadin . Vaadin usa Atmosphere por su capacidad de inserción automática. Pero cuidado, WebSocket todavía es relativamente nuevo con muchos cambios en su definición, especificaciones y diversas implementaciones durante su breve historia. Así que espere "problemas" sin importar cómo vaya.
Basil Bourque
2
Para su información, Autobahn está ahí afuera y tienen un sitio web llamativo. Pero no note que "los WebSockets seguros no están implementados" hasta que pase el tiempo de instalar e intentar ejecutarlo. Próximo.
cloudsurfin
1
No tengo suficiente reputación para comentar, así que lo escribo como respuesta, ya que cumplí con los mismos requisitos que mencionó en su pregunta y okhttp me ayudó a satisfacer todos los requisitos. Admite sockets web desde la introducción de la versión 3.5, por lo que es una ventaja adicional usar okHttp (llamadas de servicio web + soporte de sockets web). Aquí está el enlace para comenzar. < medium.com/@ssaurel/… >
Kaleem Patel
77
Preguntas como esta no deberían cerrarse.
Martin Berger

Respuestas:

123

Algunas notas.

  • koush / AndroidAsync no realiza el apretón de manos de cierre requerido por RFC 6455 . Vea esto para más detalles.

  • Project Tyrus funciona en Android, pero asegúrese de que su licencia ( CDDL 1.1 y GPL 2 con CPE ) y su tamaño ( Reducción del tamaño de jar del cliente WebSocket con ProGuard ) cumplan con sus requisitos. También tenga en cuenta que Tyrus puede lanzar una excepción cuando el tamaño del texto es grande (probablemente sea un error). Vea esto para más detalles.

  • Jetty : un hilo de correo electrónico de hace 2 años en la lista de correo de usuarios de embarcaderos dice: "Actualmente no tenemos un cliente JetS 9 WebSocket compatible con Android. Hay planes para intentar hacer una copia de respaldo del cliente Jetty WebSocket de JDK 7 a JDK 5/6 para Android uso, pero es una prioridad menor que terminar nuestra implementación de la API JSR-356 Java WebSocket (javax.websocket) ". El documento actual de Jetty sobre su API de cliente WebSocket no menciona nada sobre Android.

  • codebutler / android-websocket no realiza el apretón de manos de cierre requerido por RFC 6455 y puede lanzar una excepción al cerrar. Mira esto .

  • Atmosphere / wasync usa AsyncHttpClient / async-http-client como su implementación de WebSocket. Entonces, más bien, debería mencionarse AsyncHttpClient / async-http-client.

  • firebase / TubeSock no verifica Sec-WebSocket-Accept. Esta es una violación contra RFC 6455 . Además, TubeSock tiene un error al crear un mensaje de texto. Encontrará el error tarde o temprano si utiliza caracteres UTF-8 de varios bytes para mensajes de texto. Consulte el número 3 en delight-im / Android-DDP para obtener una larga lista sobre los problemas de TubeSock.

Puntos de consideración

Puntos de consideración al seleccionar una implementación de cliente WebSocket escrita en Java:

  1. El cumplimiento . No pocas implementaciones implementan el apretón de manos de cierre requerido por RFC 6455 . (¿Qué sucede si no se implementa el apretón de manos de cierre? Vea esto ).
  2. Se requiere la versión de Java . Java SE 5, 6, 7, 8 o Java EE? Funciona incluso en Android?
  3. Tamaño . Algunas implementaciones tienen muchas dependencias.
  4. soporte de wss .
  5. Soporte de proxy HTTP .
  6. wss sobre soporte de proxy HTTP . Consulte la Figura 2 en Cómo interactúan los sockets web HTML5 con los servidores proxy acerca de lo que debe hacer una biblioteca cliente WebSocket para admitir wss a través del proxy HTTP.
  7. Flexibilidad en la configuración SSL . SSLSocketFactoryy SSLContextdebe poder utilizarse sin restricciones innecesarias.
  8. Encabezados HTTP personalizados en el protocolo de enlace inicial , incluida la autenticación básica.
  9. Encabezados HTTP personalizados en la negociación de proxy HTTP , incluida la autenticación en el servidor proxy.
  10. Capaz de enviar todos los tipos de trama (continuación, binario, texto, cierre, ping y pong) o no. La mayoría de las implementaciones no proporcionan a los desarrolladores medios para enviar cuadros fragmentados y cuadros pong no solicitados manualmente.
  11. Interfaz de escucha para recibir varios eventos de WebSocket. Una interfaz pobre hace que los desarrolladores se sientan frustrados. Una interfaz rica ayuda a los desarrolladores a escribir aplicaciones robustas.
  12. Capaz de consultar el estado de WebSocket o no. RFC 6455 define los estados de CONEXIÓN, ABIERTO, CIERRE y CERRADO, pero pocas implementaciones mantienen su transición de estado interno de la manera definida.
  13. Capaz de establecer un valor de tiempo de espera para la conexión de socket . (Equivalente al segundo argumento del método)Socket.connect(SocketAddress endpoint, int timeout)
  14. Capaz de acceder al zócalo sin procesar subyacente .
  15. API intuitiva fácil de usar o no.
  16. Bien documentado o no.
  17. Soporte RFC 7692 (Extensiones de compresión para WebSocket) (también conocido como permessage-deflate).
  18. Redirección (3xx) de apoyo.
  19. Soporte de autenticación de resumen .

nv-websocket-client cubre todo lo anterior excepto los dos últimos. Además, una de sus características pequeñas pero convenientes es enviar periódicamente cuadros de ping / pong. Se puede lograr simplemente llamandosetPingInterval/setPongIntervalmétodos (ver JavaDoc ).

Descargo de responsabilidad: Takahiko Kawasaki es el autor de nv-websocket-client.

Takahiko Kawasaki
fuente
1
¿Está todavía en desarrollo la biblioteca nv-websocket-client? Me enfrenté al problema de desconexión automática con TooTallNate / Java-WebSockets con el error 1006 y SIN motivo ... ¿este nv-websocket también lo resuelve?
Ankit Bansal
1
En cuanto a 1006, la especificación (RFC 6455) establece que el código NO DEBE establecerse como un código de estado en un marco de control Cerrar por un punto final . Esto significa que el código se generó en el lado del cliente. Puede obtener más información sobre la desconexión a través del onDisconnectedmétodo y el onErrormétodo de WebSocketListener . onErrorEl método te da una WebSocketExceptioninstancia. Llame a su getError()método para ver cuál es el problema.
Takahiko Kawasaki
77
Para wss, probé okhttp y autobahn (también sospechoso de la autopromoción en esta respuesta). Autobahn fue fácil, pero no tiene SSL. OkHttp tiene poca o cero documentación (consolidada) (febrero de 2016). Perdí mucho tiempo leyendo su código y sus excepciones porque no estaba al tanto de las soluciones (como establecer el tiempo de espera en 0 o cerrar el mensaje entrante) para que funcionara un ejemplo básico. Al deshacerme de esos dos (y mi frustración), encontré nv (refrescante) bien documentado; Funcionó sin problemas.
cloudsurfin
1
¿Alguna idea sobre el nuevo soporte websockets de Square / okhttp? medium.com/square-corner-blog/…
scorpiodawg
2
No sé detalles sobre OkHttp. Lo siento, estoy tan ocupado como el fundador de Authlete, Inc. ("El inicio de seguridad API Authlete recauda $ 1.2 millones en fondos iniciales ") No puedo perder tiempo para buscar en OkHttp y actualizar la lista de puntos de consideración. Con respecto a los cambios desde mi respuesta, vea CHANGES.md . Tenga en cuenta que nv-websocket-client es solo mi pasatiempo, mientras que OkHttp parece un gran proyecto con 138 colaboradores.
Takahiko Kawasaki
4

Algunas otras consideraciones:

Tyrus funciona en Android. Sin embargo, las bibliotecas SSL que usa en Android 5.0 tienen errores y fallan los protocolos de enlace SSL . Se supone que esto se arregla en las versiones más recientes de Android, pero con la forma en que Android no se actualiza en muchos dispositivos, esto puede ser un problema para usted.

Dependiendo de cómo se implemente SSL para otras implementaciones de websocket, esto también puede ser un problema.

AndroidAsync no tiene este problema de SSL. Tiene otros problemas, como no poder establecer tiempos de espera .

Mattm
fuente
3

a) Agregue este archivo en el archivo gradle

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

b) Agregue estas líneas en la Actividad de la aplicación:

    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) Agregue esta función a su actividad, donde llamó a 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(() -> {


            });
        }
    };
Anil Singhania
fuente
Esto no es compatible con ws: // protocolo.
Girish Bhutiya