Quale libreria WebSocket utilizzare nell'app Android? [chiuso]


131

Voglio aggiungere un servizio alla mia app Android che viene eseguito in background con una connessione WebSocket (possibilmente per diverse ore o addirittura giorni) e invia regolarmente alcuni dati a un server.

Ora sembra che ci siano un sacco di librerie WebSocket per Java, e non sono sicuro di quale dovrei usare:

Inoltre, esiste una libreria client socket.io nativa per Android:

Utilizzare il client Android socket.io sarebbe utile per me, perché ho intenzione di utilizzare nodejs / socket.io per il frontend web comunque. Ma il client nativo è piuttosto giovane e ha diversi problemi aperti. Inoltre, è mia comprensione che un'app Android non ha alcun vantaggio nell'utilizzare la libreria client socket.io (oltre ad essere compatibile con il server socket.io 1.0), perché il supporto WebSocket può essere assicurato sul lato client .

I miei requisiti sono i seguenti:

  • Compatibilità con API Android 9 e successive
  • Possibilità di connettersi tramite SSL
  • Mantieni la connessione a lungo senza dover tenere un wakelock permanente
  • Compatibilità con un'implementazione del server websocket nodejs disponibile o con socket.io

Qualche suggerimento qual è la libreria giusta per questi requisiti?



2
Non sono esperto di WebSocket né atmosfera. So solo che Atmosphere è logoro, utilizzato in molti progetti per le funzionalità Push , incluso il supporto WebSocket. La mia unica esperienza è indiretta nella creazione di app Web Vaadin . Vaadin utilizza Atmosphere per la sua funzionalità Push automatica. Ma attenzione, WebSocket è ancora relativamente nuovo con molte modifiche alla sua definizione, alle specifiche e alle varie implementazioni nel corso della sua breve storia. Quindi aspettati "problemi", non importa come vai.
Basil Bourque,

2
Cordiali saluti, Autobahn è là fuori e hanno un sito Web appariscente. Ma non si noti che "WebSocket sicuri non implementati" fino a quando non si impiega il tempo necessario per l'installazione e provare a eseguirlo. Il prossimo.
cloudsurfin,

1
Non ho abbastanza reputazione per commentare, quindi lo scrivo come risposta poiché ho superato gli stessi requisiti menzionati nella tua domanda e okhttp mi ha aiutato a soddisfare tutti i requisiti. Supporta i web socket dall'introduzione della versione 3.5, quindi è un ulteriore vantaggio usare okHttp (chiamate ai servizi web + supporto dei web socket). Ecco il link per iniziare. < medium.com/@ssaurel/… >
Kaleem Patel,

7
Domande come questa non dovrebbero essere chiuse.
Martin Berger,

Risposte:


123

Alcune note

  • koush / AndroidAsync non esegue l' handshake di chiusura richiesta da RFC 6455 . Vedi questo per i dettagli.

  • Project Tyrus funziona su Android, ma assicurati che la sua licenza ( CDDL 1.1 e GPL 2 con CPE ) e le sue dimensioni ( Riduzione della dimensione del vaso client WebSocket con ProGuard ) soddisfino le tue esigenze. Si noti inoltre che Tyrus può generare un'eccezione quando una dimensione del testo è grande (probabilmente è un bug). Vedi questo per i dettagli.

  • Jetty : un thread di e - mail di 2 anni fa nella mailing list degli utenti di molo dice "Al momento non abbiamo client Jetty 9. WebSocket compatibile con Android. Ci sono piani per tentare di eseguire il backport del client Jetty WebSocket da JDK 7 a JDK 5/6 per Android utilizzare, ma è una priorità inferiore rispetto al completamento della nostra implementazione dell'API Java WebSocket JSR-356 (javax.websocket). " L'attuale documento di Jetty sulla sua API client WebSocket non menziona nulla su Android.

  • codebutler / android-websocket non esegue l' handshake di chiusura richiesta da RFC 6455 e potrebbe generare un'eccezione alla chiusura. Vedere questo .

  • Atmosphere / wasync utilizza AsyncHttpClient / async-http-client come implementazione WebSocket. Quindi, piuttosto, dovrebbe essere menzionato invece AsyncHttpClient / async-http-client.

  • firebase / TubeSock non verifica Sec-WebSocket-Accept. Questa è una violazione contro RFC 6455 . Inoltre, TubeSock ha un bug nella creazione di un messaggio di testo. Incontrerai il bug prima o poi se utilizzi caratteri UTF-8 multi-byte per i messaggi di testo. Vedi il numero 3 in delight-im / Android-DDP per un lungo elenco di problemi di TubeSock.

Punti di considerazione

Punti da considerare nella selezione di un'implementazione client WebSocket scritta in Java:

  1. Compliance . Non un numero limitato di implementazioni non implementa la stretta di mano di chiusura richiesta da RFC 6455 . (Cosa succede se l'handshake di chiusura non è implementata? Vedi questo .)
  2. Versione Java richiesta . Java SE 5, 6, 7, 8 o Java EE? Funziona anche su Android?
  3. Dimensioni . Alcune implementazioni hanno molte dipendenze.
  4. supporto wss .
  5. Supporto proxy HTTP .
  6. Supporto proxy wss su HTTP . Vedere la Figura 2 in Come i Web Socket HTML5 interagiscono con i server proxy su cosa deve fare una libreria client WebSocket per supportare il proxy wss su HTTP.
  7. Flessibilità sulla configurazione SSL . SSLSocketFactorye SSLContextdovrebbe essere in grado di essere utilizzato senza inutili restrizioni.
  8. Intestazioni HTTP personalizzate nell'handshake di apertura , inclusa l'autenticazione di base.
  9. Intestazioni HTTP personalizzate nella negoziazione del proxy HTTP , inclusa l'autenticazione sul server proxy.
  10. In grado di inviare tutti i tipi di frame (continuazione, binario, testo, chiudi, ping e pong) o meno. La maggior parte delle implementazioni non fornisce agli sviluppatori i mezzi per inviare manualmente frame frammentati e frame pong non richiesti .
  11. Interfaccia del listener per ricevere vari eventi WebSocket. Un'interfaccia scadente rende gli sviluppatori frustrati. Una ricca interfaccia aiuta gli sviluppatori a scrivere applicazioni robuste.
  12. In grado di informarsi sullo stato di WebSocket o meno. RFC 6455 definisce gli stati CONNECTING, OPEN, CLOSING e CLOSED, ma poche implementazioni mantengono la transizione di stato interna nel modo definito.
  13. In grado di impostare un valore di timeout per la connessione socket . (Equivalente al secondo argomento del metodo)Socket.connect(SocketAddress endpoint, int timeout)
  14. In grado di accedere al socket raw sottostante .
  15. API intuitiva e facile da usare o meno.
  16. Ben documentato o no.
  17. Supporto RFC 7692 (estensioni di compressione per WebSocket) (aka permessage-deflate).
  18. Supporto di reindirizzamento (3xx).
  19. Supporto per autenticazione digest .

nv-websocket-client copre tutto quanto sopra tranne gli ultimi due. Inoltre, una delle sue caratteristiche piccole ma convenienti è l'invio periodico di frame da ping / pong. Può essere ottenuto semplicemente chiamandosetPingInterval/setPongIntervalmethod (Vedi JavaDoc ).

Disclaimer: Takahiko Kawasaki è l'autore di nv-websocket-client.


1
la libreria nv-websocket-client è ancora in fase di sviluppo? Ho riscontrato un problema di disconnessione automatica con TooTallNate / Java-WebSocket con errore 1006 e NESSUN motivo. Questo nv-websocket lo risolve anche?
Ankit Bansal,

1
Per quanto riguarda 1006, la specifica (RFC 6455) afferma che il codice NON DEVE essere impostato come codice di stato in un frame di controllo Close da un endpoint . Ciò significa che il codice è stato generato sul lato client. È possibile ottenere ulteriori informazioni sulla disconnessione tramite il onDisconnectedmetodo e il onErrormetodo di WebSocketListener . onErrorIl metodo ti dà WebSocketExceptionun'istanza. Chiama il suo getError()metodo per vedere qual è il problema.
Takahiko Kawasaki,

7
Per wss, ho provato okhttp e autobahn (anche sospetto dell'autopromozione in questa risposta). Autobahn è stato facile, ma non ha SSL. OkHttp ha poca (zero) documentazione (febbraio 2016). Ho perso molto tempo a leggere il loro codice e le loro eccezioni perché non ero a conoscenza di soluzioni alternative (come impostare il timeout su 0 o chiudere il messaggio in arrivo) per far funzionare un esempio di ossa nude. Scaricando quei due (e la mia frustrazione), ho trovato nv (rinfrescante) ben documentato; ha funzionato senza problemi.
cloudsurfin,

1
Qualche idea sul supporto dei nuovi websocket di Square / okhttp? medium.com/square-corner-blog/…
scorpiodawg

2
Non conosco dettagli su OkHttp. Mi dispiace di essere così impegnato come il fondatore di Authlete, Inc. ("La startup di sicurezza API Authlete raccoglie $ 1,2 milioni in finanziamenti seed ") Non riesco a risparmiare tempo per esaminare OkHttp e aggiornare l'elenco dei punti di considerazione. Per quanto riguarda le modifiche dalla mia risposta, vedere CHANGES.md . Nota: nv-websocket-client è solo il mio hobby, mentre OkHttp sembra un grande progetto con 138 collaboratori.
Takahiko Kawasaki,

4

Alcune altre considerazioni:

Tyrus funziona su Android. Tuttavia, le librerie SSL che utilizza in Android 5.0 sono buggy e falliscono gli handshake SSL . Questo dovrebbe essere risolto nelle versioni più recenti di Android, ma con il modo in cui Android non viene aggiornato su molti dispositivi, questo potrebbe essere un problema per te.

A seconda di come viene implementato SSL per altre implementazioni di websocket, questo potrebbe anche essere un problema.

AndroidAsync non ha questo problema SSL. Ha altri problemi come non essere in grado di impostare i timeout .


3

a) Aggiungi questo file nel file gradle

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

b) Aggiungi queste righe nell'attività dell'applicazione:

    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) Aggiungi questa funzione alla tua attività, dove hai chiamato 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(() -> {


            });
        }
    };

Questo non supporta il protocollo ws: //.
Girish Bhutiya,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.