Chcę dodać usługę do mojej aplikacji na Androida, która działa w tle, utrzymując połączenie WebSocket (prawdopodobnie przez kilka godzin lub nawet dni) i regularnie wysyła niektóre dane na serwer.
Teraz wydaje się, że jest kilka bibliotek WebSocket dla Javy i nie jestem pewien, której powinienem użyć:
TooTallNate / Java-WebSocket Opis z GitHub: Podstawowa implementacja klienta i serwera WebSocket napisana w 100% w Javie. http://java-websocket.org/ - ten link znajduje się w moim pierwszym wyniku wyszukiwania w Google „android websocket” . Jednak ma kilka otwartych problemów, zwłaszcza dotyczących połączeń SSL, i wydaje się, że w tej chwili nie jest aktywnie obsługiwany.
koush / AndroidAsync Opis z GitHub: asynchroniczne gniazdo, http (klient + serwer), websocket i biblioteka socket.io dla systemu Android. Oparty na nio, a nie wątkach. - Znowu wiele otwartych kwestii, ale wydaje się, że są aktywnie utrzymywane / nad którymi pracowano.
Opis projektu Tyrus ze strony internetowej: JSR 356: Java API dla WebSocket - implementacja referencyjna - jest wykonana przez Oracle. Nie jestem pewien, czy działa w systemie Android.
Informacje o interfejsie API klienta Jetty WebSocket ze strony internetowej: Jetty udostępnia również bibliotekę klienta Jetty WebSocket do pisania, która ułatwia komunikację z serwerami WebSocket. - Znowu: nie jestem pewien, czy działa w systemie Android.
codebutler / android-websockets Opis z GitHub: Klient Bare minimum websockets (hybi13 / RFC) dla Androida - ten jest używany w schwiz / android-websocket-example , co jest akceptowaną odpowiedzią na pytanie StackOverflow " Jak zrobić Urządzenie z systemem Android ma połączenie TCP z Internetem bez blokady wybudzania? ”.
Atmosphere / wasync Description from GitHub: WebSockets with fallback transports client library for Node.js, Android and Java http://async-io.org
TakahikoKawasaki / nv-websocket-client Opis z GitHub: Wysokiej jakości implementacja klienta WebSocket w Javie.
square / okhttp Opis z GitHub: Klient HTTP + SPDY dla aplikacji Android i Java. http://square.github.io/okhttp/ -
Posiada moduł Websocket .Jak wspomniał scorpiodawg , OkHttp ma wbudowaną obsługę websocket od wersji 3.5.firebase / TubeSock Opis z GitHub: Biblioteka klienta WebSocket zaimplementowana w Javie
Autobahn | Android ( GitHub ) Opis ze strony internetowej: Autobahn | Android to biblioteka sieciowa typu open source dla języka Java / Android stworzona przez projekt Autobahn, który implementuje protokół WebSocket i protokół komunikacyjny aplikacji sieci Web (WAMP) do tworzenia natywnego mobilnego protokołu WebSocket / WAMP klientów. - cloudsurfin zwrócił uwagę, że to nie obsługuje wss.
Ponadto istnieje natywna biblioteka klienta socket.io dla systemu Android:
- nkzawa / socket.io-client.java Opis z GitHub: W pełni funkcjonalna biblioteka klienta Socket.IO dla języka Java, która jest kompatybilna z Socket.IO v1.0 i nowszymi.
Korzystanie z klienta socket.io na Androida byłoby dla mnie przydatne, ponieważ i tak planuję używać nodejs / socket.io do frontendu internetowego. Ale rodzimy klient jest dość młody i ma kilka otwartych problemów. Poza tym, rozumiem, że aplikacja na Androida nie ma żadnych korzyści z używania biblioteki klienta socket.io (poza kompatybilnością z serwerem socket.io 1.0), ponieważ obsługa WebSocket może być zapewniona po stronie klienta .
Moje wymagania są następujące:
- Zgodność z Android API 9 i nowszym
- Możliwość połączenia przez SSL
- Utrzymuj połączenie przez długi czas bez konieczności utrzymywania stałego wakelocka
- Kompatybilność z dostępną implementacją serwera nodejs websocket lub z socket.io
Jakieś sugestie, która biblioteka jest odpowiednia dla tych wymagań?
Odpowiedzi:
Kilka uwag.
koush / AndroidAsync nie wykonuje uzgadniania zamykającego, które jest wymagane przez RFC 6455 . Zobacz to, aby uzyskać szczegółowe informacje.
Projekt Tyrus działa na Androidzie, ale upewnij się, że jego licencja ( CDDL 1.1 i GPL 2 z CPE ) i jego rozmiar ( Zmniejszenie rozmiaru jar klienta WebSocket z ProGuard ) spełniają Twoje wymagania. Zwróć również uwagę, że Tyrus może zgłosić wyjątek, gdy rozmiar tekstu jest duży (prawdopodobnie jest to błąd). Zobacz to, aby uzyskać szczegółowe informacje.
Molo : 2 lata temu wątek e - mailowy na liście mailingowej użytkowników molo zawiera komunikat „Obecnie nie mamy klienta Jetty 9 WebSocket zgodnego z systemem Android. Planowane są próby przeniesienia klienta Jetty WebSocket z wersji JDK 7 na JDK 5/6 dla systemu Android wykorzystania, ale jest to niższy priorytet niż zakończenie naszej implementacji JSR-356 Java WebSocket API (javax.websocket). " Obecny dokument Jetty na temat jego interfejsu API klienta WebSocket nie wspomina nic o Androidzie.
codebutler / android-websocket nie wykonuje uzgadniania zamykającego, które jest wymagane przez RFC 6455 i może zgłosić wyjątek podczas zamykania. Zobacz to .
Atmosphere / wasync używa AsyncHttpClient / async-http-client jako implementacji WebSocket. Zamiast tego należy raczej wspomnieć o AsyncHttpClient / async-http-client.
Firebase / TubeSock nie weryfikuje
Sec-WebSocket-Accept
. Jest to naruszenie RFC 6455 . Ponadto TubeSock ma błąd w tworzeniu wiadomości tekstowej. Prędzej czy później napotkasz ten błąd, jeśli używasz wielobajtowych znaków UTF-8 w wiadomościach tekstowych. Zobacz Wydanie 3 w Delight-im / Android-DDP, aby uzyskać długą listę problemów z TubeSock.Punkty do rozważenia
Punkty do rozważenia przy wyborze implementacji klienta WebSocket napisanej w języku Java:
SSLSocketFactory
iSSLContext
powinno być możliwe do wykorzystania bez zbędnych ograniczeń.Socket.connect(SocketAddress endpoint, int timeout)
nv-websocket-client obejmuje wszystkie powyższe z wyjątkiem dwóch ostatnich. Ponadto jedną z jego małych, ale wygodnych funkcji jest okresowe wysyłanie ramek ping / pong. Można to osiągnąć po prostu wywołując
setPingInterval
/ MethodssetPongInterval
(patrz JavaDoc ).Zastrzeżenie: Takahiko Kawasaki jest autorem nv-websocket-client.
źródło
onDisconnected
metody ionError
metody WebSocketListener .onError
metoda dajeWebSocketException
instancję. Wywołaj jegogetError()
metodę, aby zobaczyć, w czym jest problem.Kilka innych uwag:
Tyrus działa na Androidzie. Jednak biblioteki SSL, których używa w systemie Android 5.0, są wadliwe i nie mogą uzgadniać SSL . Ma to zostać naprawione w nowszych wersjach Androida, ale ze względu na to, że Android nie jest aktualizowany na wielu urządzeniach, może to stanowić problem.
W zależności od tego, jak SSL jest zaimplementowany w innych implementacjach protokołu internetowego, może to również stanowić problem.
AndroidAsync nie ma tego problemu z SSL. Ma inne problemy, takie jak brak możliwości ustawienia limitów czasu .
źródło
a) Dodaj ten plik w pliku gradle
compile 'com.github.nkzawa:socket.io-client:0.3.0'
b) Dodaj te wiersze w Aktywności aplikacji:
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) Dodaj tę funkcję do swojej aktywności, w której wywołałeś 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(() -> { }); } };
źródło