web-dev-qa-db-fra.com

Quelle bibliothèque WebSocket utiliser dans Android app?

Je souhaite ajouter un Service à mon application Android qui s'exécute en arrière-plan, avec une connexion WebSocket (éventuellement plusieurs heures ou même plusieurs jours) et régulièrement envoie des données à un serveur.

Maintenant, il semble y avoir un tas de bibliothèques WebSocket pour Java, et je ne suis pas sûr de celle que je devrais utiliser:

En outre, il existe une bibliothèque de clients native socket.io pour Android:

  • nkzawa/socket.io-client.Java Description de GitHub: Bibliothèque complète de clients Socket.IO pour Java, qui est compatible avec Socket.IO v1.0 et versions ultérieures.

Utiliser le client socket.io Android me serait utile, car je prévois quand même d'utiliser nodejs/socket.io pour l'interface Web. Mais le client natif est assez jeune et a plusieurs problèmes en suspens. Et en plus de cela, je crois comprendre qu'une application Android ne présente aucun avantage à utiliser la bibliothèque client socket.io (à part d'être compatible avec le serveur socket.io 1.0), car la prise en charge de WebSocket peut soyez assuré du côté du client.

Mes exigences sont les suivantes:

  • Compatibilité avec Android API 9 et versions ultérieures
  • Possibilité de se connecter via SSL
  • Gardez la connexion pendant longtemps sans avoir à tenir un wakelock permanent
  • Compatibilité avec une implémentation de serveur websocket nodejs disponible ou avec socket.io

Des suggestions qui est la bonne bibliothèque pour ces exigences?

121
x-ray

Quelques notes.

  • koush/AndroidAsync n'effectue pas le fermeture de la poignée de main requise par RFC 6455 . Voir this pour plus de détails.

  • Project Tyrus fonctionne sur Android, mais assurez-vous que sa licence ( CDDL 1.1 et GPL 2 avec CPE ) et sa taille ( Réduction de la taille du fichier jar du client WebSocket avec ProGuard ) répondez à vos exigences. Notez également que Tyrus peut émettre une exception si la taille du texte est grande (c'est probablement un bug). Voir this pour plus de détails.

  • Jetty : Il y a 2 ans fil de messagerie dans la liste de diffusion de jetty-users dit "Nous avons actuellement Aucun client <JS 9 WebSocket compatible Android compatible. Il est prévu d'essayer de transférer le client Jetty WebSocket de JDK 7 à JDK 5/6 pour une utilisation à Android, mais sa priorité est inférieure à celle de la finition. Notre implémentation de l'API WebSocket JSR-356 Java (javax.websocket). " Le document actuel de Jetty document concernant son API WebSocket Client ne mentionne rien à propos d'Android.

  • codebutler/Android-websocket n'effectue pas le établissement de la négociation requis par RFC 6455 et peut jeter une exception à la fin. Voir this .

  • Atmosphere/wasync utilise AsyncHttpClient/ async-http-client en tant que son implémentation WebSocket. Ainsi, AsyncHttpClient/async-http-client devrait plutôt être mentionné.

  • firebase/TubeSock ne vérifie pas Sec-WebSocket-Accept. Ceci est une violation contre RFC 6455 . En outre, TubeSock a un bug dans la création d'un message texte. Vous rencontrerez le bogue tôt ou tard si vous utilisez des caractères UTF-8 à plusieurs octets pour les messages texte. Voir Numéro dans delight-im/Android-DDP pour une longue liste de problèmes TubeSock.

Points à considérer

Points à prendre en compte lors de la sélection d'une implémentation client WebSocket écrite en Java:

  1. Conformité . Pas un petit nombre d'implémentations n'implémente pas le établissement de la main de clôture requis par RFC 6455 . (Que se passe-t-il si la poignée de main de fermeture n'est pas implémentée? Voir this .)
  2. Requis Java version . Java SE 5, 6, 7, 8 ou Java EE? Fonctionne même sur Android?
  3. Taille . Certaines implémentations ont de nombreuses dépendances.
  4. wss support.
  5. Proxy HTTP support.
  6. wss sur proxy HTTP support. Voir la figure 2 dans Comment HTML5 Web Sockets interagit avec les serveurs proxy sur ce qu'une bibliothèque client WebSocket doit faire pour prendre en charge le proxy wss over HTTP.
  7. Flexibilité sur la configuration SSL . SSLSocketFactory et SSLContext devraient pouvoir être utilisés sans restrictions inutiles.
  8. En-têtes HTTP personnalisés dans le poignée de main d'ouverture, y compris l'authentification de base.
  9. En-têtes HTTP personnalisés dans la négociation de proxy HTTP , y compris l'authentification sur le serveur proxy.
  10. Capable d'envoyer tous les types de trames (suite, binaire, texte, fermer, ping et pong) ou non. La plupart des implémentations ne fournissent pas aux développeurs les moyens d'envoyer cadres fragmentés et non sollicitécadres pong manuellement.
  11. Interface d'écoute pour recevoir divers événements WebSocket. Une interface médiocre rend les développeurs frustrés. Une interface riche aide les développeurs à écrire des applications robustes.
  12. Capable de demander l'état de WebSocket ou non. RFC 6455 définit les états CONNECTING, OPEN, CLOSING et CLOSED, mais peu d'implémentations conservent leur transition d'état interne de la manière définie.
  13. Possibilité de définir une valeur de délai d'attente pour la connexion socket . (Équivalent au second argument de la méthode Socket.connect(SocketAddress endpoint, int timeout))
  14. Capable d'accéder au socket brut sous-jacent .
  15. API intuitive et conviviale ou non.
  16. Bien documenté ou non.
  17. RFC 7692 (Compression Extensions for WebSocket) (alias permessage-deflate).
  18. Prise en charge de la redirection (3xx).
  19. Authentification Digest prise en charge.

nv-websocket-client couvre tout ce qui précède, à l'exception des deux derniers. En outre, l’une de ses fonctionnalités simples mais pratiques consiste à envoyer périodiquement des cadres de ping/pong. Vous pouvez y parvenir simplement en appelant les méthodes setPingInterval/setPongInterval (voir JavaDoc ).

Disclaimer: Takahiko Kawasaki est l'auteur de nv-websocket-client.

119

Quelques autres considérations:

Tyrus fonctionne sur Android. Cependant, les bibliothèques SSL utilisées dans Android 5.0 sont erronées et échec de la négociation SSL . Cela est censé être résolu dans les versions plus récentes d'Android, mais avec la façon dont Android n'est pas mis à jour sur de nombreux appareils, cela peut poser un problème.

En fonction de la manière dont SSL est implémenté pour d'autres implémentations websocket, cela peut également être un problème.

AndroidAsync n'a pas ce problème SSL. Il a d'autres problèmes comme ne pas être en mesure de définir des délais d'attente .

4
mattm

a) Ajouter ce fichier dans un fichier gradle

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

b) Ajoutez ces lignes dans l'activité d'application:

    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) Ajoutez cette fonction à votre activité, où vous avez appelé 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(() -> {


            });
        }
    };
3
Anil Singhania