Welche WebSocket-Bibliothek soll in der Android-App verwendet werden? [geschlossen]

131

Ich möchte meiner Android-App einen Dienst hinzufügen , der im Hintergrund mit einer WebSocket- Verbindung (möglicherweise über mehrere Stunden oder sogar Tage) ausgeführt wird und regelmäßig Daten an einen Server sendet.

Jetzt scheint es eine Reihe von WebSocket-Bibliotheken für Java zu geben, und ich bin mir nicht sicher, welche ich verwenden soll:

Darüber hinaus gibt es eine native socket.io-Clientbibliothek für Android:

  • nkzawa / socket.io-client.java Beschreibung von GitHub: Voll funktionsfähige Socket.IO-Clientbibliothek für Java, die mit Socket.IO v1.0 und höher kompatibel ist.

Die Verwendung des Android-Clients socket.io wäre für mich praktisch, da ich ohnehin vorhabe, nodejs / socket.io für das Web-Frontend zu verwenden. Der einheimische Kunde ist jedoch noch recht jung und hat mehrere offene Fragen. Darüber hinaus habe ich das Verständnis, dass eine Android-App keinen Nutzen aus der Verwendung der Client-Bibliothek socket.io hat (abgesehen davon, dass sie mit dem Server socket.io 1.0 kompatibel ist), da die Unterstützung von WebSocket auf der Client-Seite sichergestellt werden kann .

Meine Anforderungen sind wie folgt:

  • Kompatibilität mit Android API 9 und höher
  • Möglichkeit der Verbindung über SSL
  • Halten Sie die Verbindung für eine lange Zeit, ohne ein permanentes Wakelock halten zu müssen
  • Kompatibilität mit einer verfügbaren NodeJS-Websocket-Server-Implementierung oder mit socket.io

Irgendwelche Vorschläge, welche Bibliothek die richtige für diese Anforderungen ist?

Röntgen
quelle
Vielleicht Atmosphäre . Siehe diese Frage .
Basil Bourque
2
Ich bin kein Experte für WebSocket oder Atmosphere. Ich weiß nur, dass Atmosphere abgenutzt ist und in vielen Projekten für Push- Funktionen einschließlich WebSocket-Unterstützung verwendet wird. Meine einzige Erfahrung ist indirekt beim Erstellen von Vaadin- Webanwendungen. Vaadin verwendet Atmosphere für seine automatische Push-Funktion. Beachten Sie jedoch, dass WebSocket noch relativ neu ist und in seiner kurzen Geschichte viele Änderungen an seiner Definition, seinen Spezifikationen und verschiedenen Implementierungen vorgenommen hat. Erwarten Sie also "Probleme", egal wie Sie gehen.
Basil Bourque
2
Zu Ihrer Information, die Autobahn ist da draußen und sie haben eine auffällige Website. Beachten Sie jedoch nicht, dass "sichere WebSockets nicht implementiert" sind, bis Sie die Zeit für die Installation und den Versuch, sie auszuführen, aufwenden. Nächster.
Cloudsurfin
1
Ich habe nicht genug Ruf, um einen Kommentar abzugeben, daher schreibe ich ihn als Antwort, da ich dieselben Anforderungen durchlaufen habe, die Sie in Ihrer Frage erwähnt haben, und okhttp mir geholfen hat, alle Anforderungen zu erfüllen. Es unterstützt Web-Sockets seit Einführung der Version 3.5. Daher ist es ein zusätzlicher Vorteil, okHttp zu verwenden (Web-Service-Aufrufe + Unterstützung für Web-Sockets). Hier ist der Link zu Beginn. < medium.com/@ssaurel/… >
Kaleem Patel
7
Fragen wie diese sollten nicht geschlossen werden.
Martin Berger

Antworten:

123

Einige Notizen.

  • koush / AndroidAsync führt den für RFC 6455 erforderlichen schließenden Handshake nicht aus . Siehe dies für Details.

  • Project Tyrus funktioniert unter Android, stellen Sie jedoch sicher, dass die Lizenz ( CDDL 1.1 und GPL 2 mit CPE ) und die Größe ( Reduzierung der WebSocket-Client-JAR-Größe mit ProGuard ) Ihren Anforderungen entsprechen. Beachten Sie auch, dass Tyrus möglicherweise eine Ausnahme auslöst, wenn eine Textgröße groß ist (es ist wahrscheinlich ein Fehler). Siehe dies für Details.

  • Jetty : In einem E - Mail-Thread vor 2 Jahren in der Mailingliste für Jetty-Benutzer heißt es: "Wir haben derzeit keinen Android-kompatiblen Jetty 9-WebSocket-Client. Es ist geplant, den Jetty WebSocket-Client für Android von JDK 7 auf JDK 5/6 zurück zu portieren." verwenden, aber es hat eine niedrigere Priorität als die Fertigstellung unserer Implementierung der Java WebSocket-API JSR-356 (javax.websocket). " In Jettys aktuellem Dokument über die WebSocket Client-API wird nichts über Android erwähnt.

  • codebutler / android-websocket führt den für RFC 6455 erforderlichen schließenden Handshake nicht aus und kann beim Schließen eine Ausnahme auslösen . Sehen Sie das .

  • Atmosphere / wasync verwendet AsyncHttpClient / async-http-client als WebSocket-Implementierung. Daher sollte stattdessen AsyncHttpClient / async-http-client erwähnt werden.

  • firebase / TubeSock überprüft nicht Sec-WebSocket-Accept. Dies ist ein Verstoß gegen RFC 6455 . Außerdem hat TubeSock einen Fehler beim Erstellen einer Textnachricht. Sie werden früher oder später auf den Fehler stoßen, wenn Sie Multi-Byte-UTF-8-Zeichen für Textnachrichten verwenden. Eine lange Liste der TubeSock-Probleme finden Sie in Ausgabe 3 in Enjoy-Im / Android-DDP .

Betrachtungspunkte

Überlegungen bei der Auswahl einer in Java geschriebenen WebSocket-Client-Implementierung:

  1. Compliance . Nicht wenige Implementierungen implementieren nicht den für RFC 6455 erforderlichen abschließenden Handshake . (Was passiert, wenn der schließende Handshake nicht implementiert ist? Siehe dies .)
  2. Erforderliche Java-Version . Java SE 5, 6, 7, 8 oder Java EE? Funktioniert auch auf Android?
  3. Größe . Einige Implementierungen haben viele Abhängigkeiten.
  4. wss Unterstützung.
  5. HTTP-Proxy- Unterstützung.
  6. wss über HTTP-Proxy- Unterstützung. In Abbildung 2 in Wie HTML5-Web-Sockets mit Proxyservern interagieren, erfahren Sie, was eine WebSocket-Client-Bibliothek tun muss, um wss über HTTP-Proxy zu unterstützen.
  7. Flexibilität bei der SSL-Konfiguration . SSLSocketFactoryund SSLContextsollte ohne unnötige Einschränkungen verwendet werden können.
  8. Benutzerdefinierte HTTP-Header im ersten Handshake , einschließlich Standardauthentifizierung.
  9. Benutzerdefinierte HTTP-Header bei der HTTP-Proxy-Aushandlung , einschließlich der Authentifizierung auf dem Proxyserver.
  10. Kann alle Rahmentypen (Fortsetzung, Binär, Text, Schließen, Ping und Pong) senden oder nicht. Die meisten Implementierungen bieten Entwicklern keine Möglichkeit, fragmentierte Frames und unerwünschte Pong-Frames manuell zu senden .
  11. Listener-Schnittstelle zum Empfangen verschiedener WebSocket-Ereignisse. Eine schlechte Benutzeroberfläche macht Entwickler frustriert. Eine umfangreiche Benutzeroberfläche hilft Entwicklern beim Schreiben robuster Anwendungen.
  12. Kann den WebSocket-Status abfragen oder nicht. RFC 6455 definiert die Zustände CONNECTING, OPEN, CLOSING und CLOSED, aber nur wenige Implementierungen behalten ihren internen Zustandsübergang auf die definierte Weise bei.
  13. Kann einen Timeout-Wert für die Socket-Verbindung festlegen . (Entspricht dem zweiten Argument der Methode)Socket.connect(SocketAddress endpoint, int timeout)
  14. Zugriff auf den zugrunde liegenden Raw-Socket .
  15. Intuitive benutzerfreundliche API oder nicht.
  16. Gut dokumentiert oder nicht.
  17. Unterstützung für RFC 7692 (Compression Extensions for WebSocket) (auch bekannt als Permessage-Deflate).
  18. Umleitungsunterstützung (3xx).
  19. Unterstützung für die Digest-Authentifizierung .

nv-websocket-client deckt alle oben genannten Punkte mit Ausnahme der letzten beiden ab. Darüber hinaus besteht eine der kleinen, aber praktischen Funktionen darin, regelmäßig Ping / Pong-Frames zu senden. Dies kann nur durch Aufrufen vonsetPingInterval/setPongIntervalMethoden erreicht werden (siehe JavaDoc ).

Haftungsausschluss: Takahiko Kawasaki ist der Autor von nv-websocket-client.

Takahiko Kawasaki
quelle
1
Ist die NV-Websocket-Client-Bibliothek noch in der Entwicklung? Ich hatte ein Problem mit der automatischen Trennung von TooTallNate / Java-WebSockets mit Fehler 1006 und KEINEM Grund. Behebt dieses NV-Websocket es auch?
Ankit Bansal
1
Wie für 1006 besagt die Spezifikation (RFC 6455), dass der Code NICHT von einem Endpunkt als Statuscode in einem Close- Steuerrahmen festgelegt werden darf . Dies bedeutet, dass der Code auf der Clientseite generiert wurde. Weitere Informationen zum Trennen der Verbindung erhalten Sie über die onDisconnectedMethode und die onErrorMethode von WebSocketListener . onErrorMethode gibt Ihnen eine WebSocketExceptionInstanz. Rufen Sie die getError()Methode auf, um das Problem zu ermitteln.
Takahiko Kawasaki
7
Für wss habe ich okhttp und autobahn ausprobiert (auch verdächtig der Eigenwerbung in dieser Antwort). Autobahn war einfach, hat aber kein SSL. OkHttp hat wenig (null) (konsolidierte) Dokumentation (Februar 2016). Ich habe viel Zeit damit verschwendet, ihren Code und ihre Ausnahmen zu lesen, weil ich nicht mit Problemumgehungen vertraut war (z. B. das Zeitlimit auf 0 setzen oder die eingehende Nachricht schließen), um ein Beispiel mit bloßen Knochen zum Laufen zu bringen. Als ich diese beiden (und meine Frustration) ablegte, fand ich nv (erfrischend) gut dokumentiert; es funktionierte ohne viel Aufhebens.
Cloudsfinfin
1
Irgendwelche Gedanken zur Unterstützung der neuen Websockets von Square / okhttp? medium.com/square-corner-blog/...
scorpiodawg
2
Ich kenne keine Details über OkHttp. Es tut mir leid, dass ich so beschäftigt bin wie der Gründer von Authlete, Inc. (" API-Sicherheitsstart Authlete sammelt Startkapital in Höhe von 1,2 Mio. USD "). Ich kann mir keine Zeit nehmen, um in OkHttp nachzuschauen und die Liste der Betrachtungspunkte zu aktualisieren. Informationen zu Änderungen seit meiner Antwort finden Sie unter CHANGES.md . Bitte beachten Sie, dass nv-websocket-client nur mein Hobby ist, während OkHttp ein großes Projekt mit 138 Mitwirkenden zu sein scheint.
Takahiko Kawasaki
4

Einige andere Überlegungen:

Tyrus funktioniert unter Android. Die in Android 5.0 verwendeten SSL-Bibliotheken sind jedoch fehlerhaft und schlagen SSL-Handshakes fehl . Dies soll in neueren Versionen von Android behoben werden. Da Android jedoch auf vielen Geräten nicht aktualisiert wird, kann dies ein Problem für Sie sein.

Abhängig davon, wie SSL für andere Websocket-Implementierungen implementiert ist, kann dies auch ein Problem sein.

AndroidAsync hat dieses SSL-Problem nicht. Es gibt andere Probleme, z. B. keine Zeitüberschreitungen festlegen zu können .

mattm
quelle
3

a) Fügen Sie diese Datei in die Gradle-Datei ein

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

b) Fügen Sie diese Zeilen in Anwendungsaktivität hinzu:

    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) Fügen Sie diese Funktion Ihrer Aktivität hinzu, in der Sie WebSocket aufgerufen haben:

     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
quelle
Dies unterstützt das Protokoll ws: // nicht.
Girish Bhutiya