- Использование сокетов в Android
- Особенности использования сокетов
- Клиентский android-сокет
- Класс Connection
- Листинг Connection
- Класс активности MainActivity
- Листинг активности
- Методы управления сокетным соединением
- Серверное приложение
- Листинг ConnectionWorker
- Серверный класс
- Листинг CallableDelay
- Листинг CallableServer
- Листинг серверного класса Server
- Какую библиотеку работы с HTTP в Android выбрать?
- Для чего это вообще?
- Немного истории
Использование сокетов в Android
Создано большое количество приложений как для Android, так и для других ОС, которые взаимодействуют друг с другом с помощью установления соединенией по сети. К таким приложениям относятся, например, мессенджеры социальных сетей WhatsApp, Viber. Как правило, для установления соединения между такими приложениями используются сокеты.
Сокет (socket) — это интерфейс, позволяющий связывать между собой программы различных устройств, находящихся в одной сети. Сокеты бывают двух типов: клиентский (Socket) и серверный (ServerSocket). Главное различие между ними связано с тем, что сервер «открывает» определенный порт на устройстве, «слушает» его и обрабатывает поступающие запросы, а клиент должен подключиться к этому серверу, зная его IP-адрес и порт. В Android сокеты для передачи данных используют по умолчанию протокол TCP/IP, важной особенностью которого является гарантированная доставка пакетов с данными от одного устройства до другого.
Особенности использования сокетов
Что важно знать при использовании сокетов в Android ?
- соединения сокетов отключаются при переходе устройства в спящий режим;
- чтобы не «рвать» соединение при наступлении спящего режима в устройстве можно использовать сервис;
- для использования интернет-сети необходимо Android-приложению предоставить нужные права в манифесте.
Для определения прав в манифесте необходимо в файл AndroidManifest.xml добавить следующую строку :
Теперь android-приложения будет иметь доступ к сети.
Далее в статье рассмотрим пример клиент-серверного сокетного соединения с передачей сообщения. Функции клиента будет выполнять android-приложение. Серверное java-приложение выполним в IDE Eclipse с использованием пакета concurrent. В конце страницы можно скачать оба приложения.
Клиентский android-сокет
Интерфейс andriod-приложения представлен на следующем скриншоте. Форма приложения включает поле ввода текстового сообщения и кнопки установления соединения сервером, передачи сообщения и закрытия соединения.
Клиентское приложение создадим из двух классов : класс взаимодействия с серверным сокетом Connection и класс стандартной активности MainActivity.
Класс Connection
Класс взаимодействия с сервером Connection получает при создании (через конструктор) параметры подключения : host и port. Методы Connection вызываются из активности и выполняют следующие функции :
Метод | Описание |
---|---|
openConnection | Метод открытия сокета/соединения. Если сокет открыт, то он сначала закрывается. |
closeConnection | Метод закрытия сокета |
sendData | Метод отправки сообщения из активности. |
finalize | Метод освобождения ресурсов |
Листинг Connection
Класс активности MainActivity
В активности MainActivity определены параметры сервера : host, port. Помните, что IP-адрес сервера для Вашего android-примера не может быть localhost (127.0.0.1), иначе Вы будете пытаться связаться с сервером внутри Andriod-системы. Кнопки интерфейса связаны с методами обращения к классу Connection. Кнопки отправки сообщения mBtnSend и закрытия соединения mBtnClose с сервером блокируются при старте приложения. После установления соединения с сервером доступ к кнопкам открывается.
Листинг активности
Методы управления сокетным соединением
Ниже представлены методы обработки событий, связанных с нажатием кнопок интерфейса. Обратите внимание, что подключение к серверу выполняется в отдельном потоке, а открытие доступа к кнопкам в основном потоке, для чего вызывается метод runOnUiThread. Для отправки сообщения серверу также создается отдельный поток.
Серверное приложение
Серверное приложение включает 2 класса : Server и ConnectionWorker. Серверный класс Server будет выполнять обработку взаимодействия с клиентом с использованием ConnectionWorker в отдельном потоке. Конструктор ConnectionWorker в качестве параметра получает объект типа Socket для чтения сообщений клиента из потока сокета.
Листинг ConnectionWorker
ConnectionWorker получает входной поток inputStream из клиентского сокета и читает сообщение. Если сообщение отсутствует, т.е. количество прочитанных байт равно -1, то это значит, что соединение разорвано, то клиентский сокет закрывается. При закрытии клиентского соединения входной поток сокета также закрывается.
Серверный класс
Серверный класс Server создадим с использованием многопоточного пакета util.concurrent. На странице описания сетевого пакета java.net и серверного ServerSocket был приведен пример серверного модуля с использованием обычного потока Thread, при работе с которым необходимо решать задачу его остановки : cтарый метод Thread.stop объявлен Deprecated и предан строжайшей анафеме, а безопасная инструкция Thread.interrupt безопасна, к сожалению, потому, что ровным счетом ничего не делает (отправляет сообщение потоку : «Пожалуйста, остановись»). Услышит ли данный призыв поток остается под вопросом – все зависит от разаработчика.
Чтобы иметь возможность остановить сервер «снаружи» в серверный класс Server включим 2 внутренних реализующих интерфейс Callable класса : CallableDelay и CallableServer. Класс CallableDelay будет функционировать определенное время, по истечении которого завершит свою работу и остановит 2-ой серверный поток взаимодействия с клиентами. В данном примере CallableDelay используется только для демонстрации остановки потока, организуемого пакетом util.concurrent.
Листинг CallableDelay
CallableDelay организует цикл с задержками. После завершения последнего цикла cycle поток завершает цикл, останавливает вторую задачу futureTask[1] и закрывает сокет. В консоль выводится соответствующее сообщение.
Листинг CallableServer
Конструктор CallableServer в качестве параметров получает значение открываемого порта для подключения клиентов. При старте (метод call) создается серверный сокет ServerSocket и поток переходит в режим ожидания соединения с клиентом. Остановить поток можно вызовом метода stopTask, либо завершением «задачи» типа FutureTask с данным потоком.
При подключении клиента метод serverSoket.accept возвращает сокет, который используется для создания объекта ConnectionWorker и его запуска в отдельном потоке. А сервер (поток) переходит к ожиданию следующего подключения.
В случае закрытия сокета (завершение внешней задачи FutureTask с данным потоком) будет вызвано исключение Exception, где выполняется проверка закрытия сокета; при положительном ответе основной цикл прерывается и поток завершает свою работу.
Листинг серверного класса Server
Cерверный класс Server создает два потоковых объекта (callable1, callable2), формирует из них две задачи futureTask и запускает задачи на выполнение методом execute исполнителя executor. После этого контролируется завершение выполнение обоих задач методом isTasksDone. При завершении выполнения обеих задач завершается также и цикл работы executor’а.
Два внутренних описанных выше класса (CallableDelay, CallableServer) не включены в листинг.
Источник
Какую библиотеку работы с HTTP в Android выбрать?
Представляю вашему вниманию перевод статьи «Which Android HTTP library to use?».
Для чего это вообще?
Немного истории
До Froyo HttpURLConnection имел некоторые не очень приятные баги. В частности, вызов close() у читаемого InputStream мог испортить пул соединений.
… большой размер их API мешает нам улучшать эту библиотеку без потери обратной совместимости. Команда Android не работает активно над Apache HTTP Client.
Apache HTTP client имеет мало багов на Eclair и Froyo, поэтому он является лучшим выбором для этих версий. А для Gingerbread и младше лучше подходит HttpURLConnection. Простота API и небольшой вес хорошо подходят для Android. Прозрачное сжатие и кэширование ответов помогают увеличить скорость и сохранить батарею. Новые приложения должны использовать HttpURLConnection.
Даже сегодня, если вы загляните в исходники Volley от Google (о ней я расскажу чуть попозже), вы сможете найти такое наследие:
Это классический пример фрагментации Android, которая заставляет страдать разработчиков. В 2013 году Square обратила внимание на эту проблему, когда выпускала OkHttp. OkHttp была создана для прямой работы с верхним уровнем сокетов Java, при этом не используя какие-либо дополнительные зависимости. Она поставляется в виде JAR-файла, так что разработчики могут использовать ее на любых устройствах с JVM (куда мы включаем, конечно, и Android). Для упрощения перехода на их библиотеку, Square имплементировали OkHttp используя интерфейсы HttpUrlConnection и Apache client.
OkHttp получила большое распространение и поддержку сообществом, и, в конце-концов, Google решили использовать версию 1.5 в Android 4.4 (KitKat). В июле 2015 Google официально признала AndroidHttpClient, основанный на Apache, устаревшим, вместе с выходом Android 5.1 (Lolipop).
Сегодня OkHttp поставляется со следующим огромным набором функций:
- Поддержка HTTP/2 и SPDY позволяет всем запросам, идущим к одному хосту, делиться сокетом
- Объединение запросов уменьшает время ожидания (если SPDY не доступен)
- Прозрачный GZIP позволяет уменьшить вес загружаемой информации
- Кэширование ответов позволяет избежать работу с сетью при повторных запросах.
- Поддержка как и синхронизированных блокирующих вызовов, так и асинхронных вызовов с обратным вызовом (callback)
Моя самая любимая часть OkHttp – как красиво и аккуратно можно работать с асинхронными запросами:
Это очень удобно, так как работа с сетью не должна быть в UI потоке. По-факту, начиная с Android 3.0 (Honeycomb, API 11), работа с сетью в отдельном потоке стала обязательной. Для того, чтобы воплотить что-то похожее с HtttpUrlConnection, вам потребуется построить большую (а может и монструозную) конструкцию с использованием AsyncTask или отдельного потока. Это будет еще более сложным, если вы захотите добавить отмену загрузки, объединение соединений и т.п.
Кстати, не осталась у обочины и HTTP библиотека от Google под названием Volley, которая предоставляет нам следующие бонусы:
- Автоматическое планирование сетевых запросов
- Множество параллельных сетевых соединений
- Прозрачное кэширование в памяти и на диске, в соответствии со стандартной кэш-согласованностью.
- Поддержка приоритизации запросов.
- Отмена API запросов. Вы можете отменить как один запрос, так и целый блок.
- Простота настройки, например, для повторов и отсрочек.
- Строгая очередность, которая делает легким корректное заполнение данными, полученными асинхронно из сети, интерфейса пользователя.
- Инструменты отладки и трассировки
Все, что ни есть в Volley, находится на вершине HttpUrlConnection. Если вы хотите получить JSON или изображение, то Volley имеет на это специальный абстракции, такие как ImageRequest и JsonObjectRequest, которые помогают вам в автоматическом режиме конвертировать полезную нагрузку HTTP. Так же достойно внимания то, что Volley использует жестко запрограммированный размер сетевого пула:
Когда OkHttp использует поток для каждого вызова с ThreadPoolExecutor с максимальным значением Integer.MAX_VALUE:
В результате, в большинстве случаев OkHttp будет действовать быстрее за счет использования бОльшего количества потоков. Если по каким-то причинам вы захотите использовать OkHttp вместе Volley, то есть реализация HttpStack, которая использует API запросов/ответов из OkHttp заместо HttpURLConnection.
HTTP клиенты продолжили развиваться для поддержки приложений с большим количеством картинок, особенно тех, кто поддерживает бесконечную прокрутку и трансформацию изображений. В то же время, REST API стал стандартом в индустрии, и каждый разработчик имел дело с такими типовыми задачами как сериализация в/из JSON и преобразование REST-вызовов в интерфейсы Java. Не прошло много времени, как появились библиотеки, решающие эти задачи:
- Retrofit – типобезопасный HTTP Android клиент для взаимодействия с REST-интерфейсами
- Picasso – мощная библиотека для загрузки и кэширования изображений под Android
Retrofit предоставляет некий мост между Java кодом и REST-интерфейсом. Он позволяет быстро включить в ваш проект HTTP API интерфейсы, и генерирует самодокументирующуюся реализацию.
В дополнение ко всему, Retrofit поддерживает конвертацию в JSON, XML, протокол буферов (protocol buffers).
Picasso, с другой стороны, предоставляет HTTP библиотеку, ориентированную на работу с изображениями. Например, вы можете загрузить изображение в свой View с помощью одной строчки:
Picasso и Retrofi настроены так, чтобы использовать OkHttpClient как стандартный HTTP клиент. Однако, если хотите, вы можете указать клиентом HttpURLConnection.
Glide – что-то похожее на Picasso. Он предоставляет некоторые дополнительные функции, такие как GIF-анимация, генерация миниатюрных эскизов изображения и неподвижные видео. Полное сравнение можно найти здесь.
Facebook недавно открыли общественности исходный код библиотеки Fresco, которую они используют в своем мобильном приложении. Одна из ключевых функций, которая выделяет ее, — кастомная стратегия выделения памяти для bitmap’ов, чтобы избежать работы долгого GC (сборщик мусора). Fresco выделяет память в регионе, который называется ashmem. Используются некие трюки, чтобы иметь доступ к этому региону памяти доступ как из части, написанной на C++, так и из части на Java. Чтобы уменьшить потребление CPU и данных из сети, эта библиотека использует 3 уровня кэша: 2 в ОЗУ, третий во внутреннем хранилище.
Я нашел необходимым показать отношения между библиотеками на одной схеме. Как вы можете увидеть, HTTP всегда остается внизу у высокоуровневых библиотек. Вы можете выбирать между простым HttpUrlConnection или последним OkHttpClient. Мы используем эту совместимость при разработке PacketZoom Android SDK, о котором мы поговорим в следующем посте.
Недавно мы сравнивали между собой HTTP библиотеки по производительности, но эта тема заслужила отдельного рассмотрения. Мы надеемся, что этот обзор дал вам основные идеи о плюсах и минусах каждой библиотеки, и мы помогли вам сделать правильный выбор. Следите за выходом более интересных постов о сетевой работе в Android от нас.
Источник