Какую библиотеку WebSocket использовать в приложении для Android? [закрыто]

131

Я хочу добавить службу в свое приложение для Android, которое работает в фоновом режиме с подключением WebSocket (возможно, в течение нескольких часов или даже дней) и регулярно отправляет некоторые данные на сервер.

Теперь, похоже, есть куча библиотек WebSocket для Java, и я не уверен, какую из них мне следует использовать:

Кроме того, есть собственная клиентская библиотека socket.io для Android:

  • nkzawa / socket.io-client.java Описание с GitHub: полнофункциональная клиентская библиотека Socket.IO для Java, совместимая с Socket.IO v1.0 и новее.

Мне было бы удобно использовать Android-клиент socket.io, потому что я все равно планирую использовать nodejs / socket.io для веб-интерфейса. Но нативный клиент довольно молод, и у него есть несколько нерешенных проблем. И в дополнение к этому, насколько я понимаю, приложение для Android не имеет никаких преимуществ от использования клиентской библиотеки socket.io (кроме совместимости с сервером socket.io 1.0), потому что поддержка WebSocket может быть гарантирована на стороне клиента. ,

Мои требования следующие:

  • Совместимость с Android API 9 и выше
  • Возможность подключения через SSL
  • Сохраняйте соединение в течение длительного времени без необходимости удерживать постоянный wakelock
  • Совместимость с доступной реализацией сервера nodejs websocket или с socket.io

Есть предложения, какая библиотека подходит для этих требований?

Рентгеновский
источник
Возможно Атмосфера . См. Этот вопрос .
Basil Bourque
2
Я не эксперт ни в WebSocket, ни в атмосфере. Я знаю только, что Atmosphere хорошо зашита, используется во многих проектах для функций Push, включая поддержку WebSocket. Мой единственный опыт является косвенным, в создании веб-приложений Vaadin . Vaadin использует Atmosphere для автоматической отправки сообщений. Но будьте осторожны, WebSocket все еще относительно новый, с множеством изменений в его определениях, спецификациях и различных реализациях за его короткую историю. Так что ожидайте «проблем», как бы вы ни пошли.
Basil Bourque
2
К вашему сведению, автобан уже существует, и у них есть яркий веб-сайт. Но вы не замечаете, что «безопасные веб-сокеты не реализованы», пока вы не потратите время на установку и не попытаетесь запустить его. Следующий.
cloudsurfin
1
У меня недостаточно репутации, чтобы комментировать, поэтому я пишу это в качестве ответа, поскольку я прошел те же требования, которые вы упомянули в своем вопросе, и okhttp помог мне удовлетворить все требования. Он поддерживает веб-сокеты с момента появления версии 3.5, поэтому его дополнительным преимуществом является использование okHttp (вызовы веб-служб + поддержка веб-сокетов). Вот ссылка для начала. < medium.com/@ssaurel/… >
Калим Патель
7
Подобные вопросы не следует закрывать.
Мартин Бергер

Ответы:

123

Некоторые примечания.

  • koush / AndroidAsync не выполняет закрывающее рукопожатие, требуемое RFC 6455 . Смотрите это для деталей.

  • Project Tyrus работает на Android, но убедитесь, что его лицензия ( CDDL 1.1 и GPL 2 с CPE ) и его размер ( уменьшение размера клиентского jar-файла WebSocket с помощью ProGuard ) соответствуют вашим требованиям. Также обратите внимание, что Tyrus может вызвать исключение, если размер текста большой (вероятно, это ошибка). Смотрите это для деталей.

  • Jetty : 2 года назад в электронном потоке в списке рассылки пользователей причала говорится: «В настоящее время у нас нет Android-совместимого клиента Jetty 9 WebSocket. Есть планы попытаться выполнить обратный перенос клиента Jetty WebSocket с JDK 7 на JDK 5/6 для Android. использовать, но это более низкий приоритет, чем завершение нашей реализации JSR-356 Java WebSocket API (javax.websocket) ". В текущем документе Jetty о его API-интерфейсе WebSocket Client ничего не упоминается об Android.

  • codebutler / android-websocket не выполняет рукопожатие закрытия, которое требуется по RFC 6455, и может вызывать исключение при закрытии. Смотрите это .

  • Atmosphere / wasync использует AsyncHttpClient / async-http-client в качестве реализации WebSocket. Поэтому вместо этого следует упомянуть AsyncHttpClient / async-http-client.

  • firebase / TubeSock не проверяет Sec-WebSocket-Accept. Это нарушение RFC 6455 . Также в TubeSock есть ошибка при построении текстового сообщения. Вы столкнетесь с ошибкой рано или поздно, если будете использовать многобайтовые символы UTF-8 для текстовых сообщений. См. Выпуск 3 в delight-im / Android-DDP для получения длинного списка проблем с TubeSock.

Пункты рассмотрения

Рекомендации по выбору клиентской реализации WebSocket, написанной на Java:

  1. Соответствие . Немалое количество реализаций не реализуют закрывающее рукопожатие, требуемое RFC 6455 . (Что произойдет, если закрывающее рукопожатие не будет выполнено? См. Это .)
  2. Требуемая версия Java . Java SE 5, 6, 7, 8 или Java EE? Работает даже на Android?
  3. Размер . Некоторые реализации имеют много зависимостей.
  4. поддержка wss .
  5. Поддержка HTTP-прокси .
  6. wss через HTTP-прокси . На рис. 2 в разделе « Как веб-сокеты HTML5 взаимодействуют с прокси-серверами» показано, что клиентская библиотека WebSocket должна делать для поддержки wss через прокси-сервер HTTP.
  7. Гибкость настройки SSL . SSLSocketFactoryи SSLContextдолжны иметь возможность использовать без лишних ограничений.
  8. Настраиваемые заголовки HTTP при открытии рукопожатия , включая базовую аутентификацию.
  9. Пользовательские заголовки HTTP в согласовании HTTP-прокси , включая аутентификацию на прокси-сервере.
  10. Возможность отправки всех типов кадров (продолжение, двоичный, текст, закрытие, пинг и понг) или нет. Большинство реализаций не предоставляют разработчикам средств для отправки фрагментированных фреймов и незапрошенных фреймов pong вручную.
  11. Интерфейс слушателя для получения различных событий WebSocket. Плохой интерфейс расстраивает разработчиков. Богатый интерфейс помогает разработчикам писать надежные приложения.
  12. Может узнать состояние WebSocket или нет. RFC 6455 определяет состояния CONNECTING, OPEN, CLOSING и CLOSED, но лишь немногие реализации поддерживают переход внутреннего состояния определенным образом.
  13. Возможность установить значение тайм-аута для подключения к сокету . (Эквивалентно второму аргументу метода)Socket.connect(SocketAddress endpoint, int timeout)
  14. Возможность доступа к базовому необработанному сокету .
  15. Интуитивно понятный простой в использовании API или нет.
  16. Хорошо задокументировано или нет.
  17. Поддержка RFC 7692 (Compression Extensions for WebSocket) (также известного как permessage-deflate).
  18. Поддержка перенаправления (3xx).
  19. Поддержка дайджест-аутентификации .

nv-websocket-client охватывает все вышеперечисленное, кроме двух последних. Кроме того, одна из его небольших, но удобных функций - периодически отправлять фреймы пинг / понг. Этого можно добиться, просто вызвавsetPingInterval/setPongIntervalметоды (см. JavaDoc ).

Отказ от ответственности: Такахико Кавасаки является автором nv-websocket-client.

Такахико Кавасаки
источник
1
библиотека nv-websocket-client все еще находится в стадии разработки? Я столкнулся с проблемой автоматического отключения с TooTallNate / Java-WebSockets с ошибкой 1006 и БЕЗ причин. Этот nv-websocket также решает эту проблему?
Анкит Бансал,
1
Что касается 1006, в спецификации (RFC 6455) говорится, что код НЕ ДОЛЖЕН быть установлен конечной точкой как код состояния в кадре управления закрытием . Это означает, что код был сгенерирован на стороне клиента. Вы можете получить больше информации об отключении через onDisconnectedметод и onErrorметод WebSocketListener . onErrorметод дает вам WebSocketExceptionэкземпляр. Вызовите его getError()метод, чтобы узнать, в чем проблема.
Такахико Кавасаки
7
Для wss я попробовал okhttp и autobahn (также подозреваю в саморекламе в этом ответе). Автобан был легким, но без SSL. OkHttp практически не содержит (сводной) документации (февраль 2016 г.). Я потратил много времени на чтение их кода и их исключений, потому что я не был знаком с обходными путями (например, установил тайм-аут на 0 или закрыл входящее сообщение), чтобы заставить работать простой пример. Отбросив эти два (и свое разочарование), я обнаружил, что nv (освежающе) хорошо документированы; он работал без суеты.
cloudsurfin
1
Есть какие-нибудь мысли о поддержке новых веб-сокетов Square / okhttp? medium.com/square-corner-blog/...
scorpiodawg
2
Я не знаю подробностей об OkHttp. Мне очень жаль, что я так занят, как основатель Authlete, Inc.Стартап по безопасности API Authlete привлекает $ 1,2 млн начального финансирования »). Я не могу найти время, чтобы изучить OkHttp и обновить список вопросов, требующих внимания. По поводу изменений, внесенных после моего ответа, см. CHANGES.md . Обратите внимание: nv-websocket-client - это просто мое хобби, в то время как OkHttp кажется большим проектом со 138 участниками.
Takahiko Kawasaki
4

Некоторые другие соображения:

Tyrus работает на Android. Однако библиотеки SSL, которые он использует в Android 5.0, содержат ошибки и не поддерживают квитирование SSL . Предполагается, что это будет исправлено в более новых версиях Android, но, поскольку Android не обновляется на многих устройствах, это может быть проблемой для вас.

В зависимости от того, как SSL реализован для других реализаций веб-сокетов, это также может быть проблемой.

AndroidAsync не имеет этой проблемы с SSL. У него есть и другие проблемы, такие как невозможность установить тайм-ауты .

mattm
источник
3

а) Добавьте этот файл в файл Gradle

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

б) Добавьте эти строки в Application Activity:

    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) Добавьте эту функцию в свою деятельность, где вы вызвали 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(() -> {


            });
        }
    };
Анил Сингхания
источник
Это не поддерживает протокол ws: //.
Гириш Бхутия