Видео. Пишем полноценное клиент-сервер приложение под Android / Хабр

Основные задачи при разработке клиент-серверных приложений

Так в чем же заключается сложность создания клиент-серверных Android-приложений, которые бы удовлетворяли всем принципам, которые были описаны ранее? Есть 2 крупные проблемы, каждую из которых на самом деле можно разбить еще на большее число проблем:

  • Реализация клиент-серверного взаимодействия. Казалось бы, в чем здесь проблема? Мы все умеем выполнять запросы к серверу с использованием различных средств, обрабатывать результат и показывать его пользователю. И да, и нет. Здесь существует масса факторов. Во-первых, нужно уметь корректно обрабатывать ошибки, которые могут быть самыми разными: от отсутствия интернета и неправильных параметров в запросе, до не отвечающего сервера и ошибках в ответе. Во-вторых, в вашем приложении может быть не один запрос, а много, и вполне возможна ситуация, что вам придется комбинировать результаты этих запросов сложным образом: выполнять их параллельно, использовать результат предыдущего запроса для выполнения следующего и так далее. В-третьих, и это самое неприятное – запросы могут занимать значительное время, а пользователь часто не самый терпеливый и тихий человек – он может крутить устройство (и тогда вы потеряете текущие данные в Activity), а может и вовсе закрыть приложение, и тогда вы можете получить рассинхронизацию в данных (когда на сервере данные обновились, а приложение не знает об этом и отображает некорректную или устаревшую информацию). И все это нужно каким-то образом решать.
  • Обеспечение возможности тестирования классов, содержащих бизнес-логику приложения. Это также подразумевает под собой немало внутренних проблем. Во-первых, нужно обеспечить модульность классов. Это следует из самой сути и из самого названия Unit-тестов. Чтобы обеспечить модульность, нужно разделять классы по логическим слоям для каждого экрана. То есть вместо того, чтобы писать весь код, относящийся к одному экрану, в одной активити, нужно грамотно разделить его на несколько классов, каждый из которых будет иметь свою зону ответственности. Во-вторых, если говорить о тестах с помощью JUnit, то нужно понимать, что тестируемые таким образом классы должны содержать минимальное количество зависимостей от Android-классов, так как Java и ее виртуальная машина об этих классах не знает ничего (подробнее этот момент будет описан в лекции про тестирование). В-третьих, самая сложная логика приложения почти всегда связана с работой с данными от сервера. Мы должны протестировать различные возможные ситуации, такие как ожидаемый ответ сервера, ошибка сервера и разные ответы, приводящие к разному поведению приложения. Но при выполнении теста мы не можем по своему желанию “уронить” сервер или заставить его отдать нужные нам данные. К тому же, серверные запросы выполняются долго и асинхронно, а тесты должны работать последовательно. Все эти проблемы можно решить, если подменять реализацию сервера на определенном слое, к которому будут обращаться тестируемые классы. Все это также будет рассмотрено далее.
Читайте про операторов:  Мессенджер: что это такое в телефоне простыми словами

Эти проблемы и приходится решать при создании грамотной и правильной архитектуры, и это всегда не очень просто. Более того, иногда невозможно добиться желаемого результата, и у каждого способа есть как свои недостатки, так и достоинства. Рассмотрением всех этих способов мы и будем заниматься на протяжении курса, и после вы сможете решить, как именно вы хотите разрабатывать клиент-серверные приложения.

Longpoll

Старый добрый longpoll появился до HTML5: он отличается от ping-pong тем, что закрытие соединения не инициируется со стороны клиента или сервера. Оно остается открытым, и в него можно отправлять данные до тех пор, пока не выйдет время жизни соединения (TTL).

Это дает возможность незначительно сократить расход энергии на клиентской стороне приложения, а использование пауз между запросами – сократить требования к оперативной памяти сервера. К недостаткам можно отнести все те же требования на поддержание соединения на стороне сервера, а также обрывы соединения.

Ping-pong

Этот вариант подразумевает регулярные запросы к серверу через определенные промежутки времени. Каким бы неоднозначным не казалось такое решение, оно имеет право на существование. Так, например, работает клиентское приложение социальной сети ВК.

React-native

Еще один распространенный вариант – разработка на основе веб-технологий. Здесь лидирует React Native. Признаюсь честно, я не большой поклонник React, но постараюсь не предвзято оценить его использование. Неоспоримым преимуществом является доступность владеющих этой технологией программистов и возможность задействовать штатных веб-разработчиков для создания мобильного приложения. В основном поэтому на React Native делают в основном MVP (minimum viable product).

Если у вас есть разработчики полного цикла (full-stack), то и для серверной части вы скорее всего предпочтете использовать Node.js. React Native также неплохо поддерживает анимацию, включая анимации Lottie. К сожалению, таким же неоспоримым недостатком является очень скудная производительность приложения. Исходя из своего опыта, переписывать продукты с другим технологическим стеком приходится именно по этой причине.

Читайте про операторов:  Какие возможности для рынка открывает рекламный канал операторов связи

Видео серия

6. Полноценное Android приложение: Урок 6. Реализуем Navigation Drawer (

в процессе

Данная серия видео только началась, и как вы, возможно, уже поняли, мы планируем писать записать весь процесс реализации этого приложения и будем руководствоваться тасками, которые будем планировать в Youtrack.

p.s. Если вам интересно то, что мы делаем, то мы бы хотели, чтобы вы оставили отзыв, чего вам не хватает в этой серии уроков, или что бы вы хотели увидеть в уроках.

Выбор модели кэширования

Итак. Это была непростая тема. Теперь мы попробуем подвести итоги и вывести базовые правила использования той или иной модели кэширования.

  1. Все статические изображения должны обслуживаться по модели срока действия.
  2. Все данные, формируемые динамически, должны кэшироваться по модели валидности.
  3. Если ваш, динамически формируемый, ресурс является списком, вам следует использовать модель валидности, основанную на Last-Modified. (Например /friends). В остальных случаях следует использовать модель валидности, основанную на ETag. (Например /friends/firstname.lastname).
  4. Изображения или любые другие ресурсы, которые могут быть изменены пользователем (такие как аватар) должны также кэшироваться по модели валидности с использованием ETag. Несмотря на то, что это изображения, они не постоянны как например логотип компании. Кроме того вы просто не сможете точно рассчитать срок действия таких ресурсов.

Другой способ (более простой в реализации, но немного хакерский), это использование “ошибки URL”. Когда в ответе есть URL аватара, надо сделать часть его динамичной. Так вместо представления URL как

Гибкость и расширяемость

Для обеспечения гибкости и расширяемости клиент-серверного взаимодействия мы используем при разработке RESTful API.Хороший RESTful API — тот, который можно менять легко и просто.Сервер может считаться RESTful, если он соответствует принципам REST.

Когда вы разрабатываете API, который будет в основном использоваться мобильными устройствами, понимание и следование трем наиважнейшим принципам может быть весьма полезным.Причем не только при разработке API, но и при его поддержке и развитии в дальнейшем.

Документирование

Худшая документация, которую может написать разработчик сервера — это длинный, однообразный список вызовов API с описанием параметров и возвращаемых данных. Главная проблема такого подхода заключается в том, что внесение изменений в сервер и формат возвращаемых данных по мере развития проекта становится кошмаром.

Первым шагом мы рекомендуем подумать об основных, высокоуровневых структурах данных (моделях), которыми оперирует ваше приложение. Затем подумайте над действиями, которые можно произвести над этими компонентами. Документация по foursquare API — хороший пример, который стоит изучить перед тем как начать писать свою.

Данное API имеет набор высокоуровневых объектов, таких как места, пользователи и тому подобное. Также у них есть набор действий, которые можно произвести над этими объектами. Поскольку вы знаете высокоуровневые объекты и действия над ними в вашем продукте, создание структуры вызовов API становится проще и понятней. Например, для добавления нового места логично будет вызвать метод наподобие /venues/add

Документируйте все высокоуровневые объекты. Затем документируйте запросы и ответы на них, используя эти высокоуровневые объекты вместо простых типов данных. Вместо того, чтобы писать “Этот вызов возвращает три строковых поля, первое содержит id, второе имя, а третье описание” пишите “Этот вызов возвращает структуру (модель), описывающую место”.

Игровые приложения

К первой группе можно отнести игровые приложения из-за их специфики: требований к производительности, возможностям интерактивной анимации и используемых технологий. Основное отличие игровых приложений заключается в используемых сетевых протоколах. Например, когда приложение имеет интерактивный режим (например, режим боя в реальном времени), то может использоваться протокол на основе сетевого стека UDP. В остальных случаях для связи с серверной частью используются протоколы поверх стека TCP/IP.

Помимо этого можно выделить еще одно отличие игровых приложений – это используемый стек технологий для реализации клиентской части. В большинстве случаев игровые приложения написаны на языках отличных от тех, которые используются для создания обычных мобильных программ.

Здесь можно выделить использование движков Unity (C#), Unreal Engine и менее распространенных, таких как Cocos2dx (С ). Конечно, для некоторых игровых жанров используются и нативные языки платформы. Стоит вспомнить известную всем известную 2048, но это скорее исключение из правил.

Эта группа приложений является довольно специфичной и предполагает более высокие требования к пропускной способности каналов связи, оборудованию и уровню разработчика в целом. Разработка серверной части для игровых приложений – тема для отдельной статьи, поэтому здесь мы не будем ее разбирать.

Использование etag

ETag обычно рассчитывается на сервере с использованием алгоритмов хэширования. (Большинство серверных языков высокого уровня, таких как Java/C#/Scala обладают средствами хэширования объектов). Перед формированием ответа сервер должен рассчитать хэш объекта и добавить его в поле заголовка ETag.

Использование last-modified

Реализация использования Last-Modified не совсем проста. Давайте представим что в нашем API есть вызов, возвращающий список друзей.

Клиент – серверное разделение и единый интерфейс

RESTful сервер должен прятать от клиента как можно больше деталей своей реализации.Клиенту не следует знать о том, какая СУБД используется на сервере или сколько серверов в данный момент обрабатывают запросы и прочие подобные вещи.Организация правильного разделения функций важна для масштабирования, если ваш проект начнёт быстро набирать популярность.Это, пожалуй три самых важных принципа, которым нужно следовать в ходе разработки RESTful сервера.

Модель срока действия

Давайте рассмотрим распространенную конфигурацию кэширования. Если вы используете nginx, у вас наверняка есть в конфиге нечто подобное:

location ~ .(jpg|gif|png|ico|jpeg|css|swf)$ {
expires 7d;
}

Нативные

Классическим вариантом является использование нативных языков и их вариаций, таких как Java, Kotlin, Objective-C и Swift. К преимуществам использования нативных языков можно отнести очень высокую скорость исполнения и относительно малый размер бинарного файла, но здесь стоит учитывать и размер ассеттов (изображений, шрифтов и т.д.).

Поскольку знание нативных языков является базовым требованием для разработчика мобильных приложений, положительным фактором здесь является доступность специалистов. К недостаткам можно отнести только одно – вам придется переписывать код под каждую платформу на специфичном для нее языке.

Обычные приложения

Ко второй группе относятся офисные и развлекательные приложения, инструменты повышения производительности и т.д.

Парадигма разделения на версии через модель

Выше мы показали как документировать ваши структуры данных (модели). Рассматривайте эту документацию как контракт между разработчиками серверной и клиентской частей. Вам не следует вносить изменения в модели без изменения версии. Это значит, что в предыдущем случае должно быть две модели №1 и №2.Поведение модели №1 остается таким же, как это было оговорено в документации.

Поддержка на стороне клиента

На самом деле под iOS, если вы используете MKNetworkKit, то он делает всю работу автоматически.

[[MKNetworkEngine sharedEngine] useCache];

Поддержка старых версий api

До появления мобильных приложений, в эпоху Web 2.0 создание разных версий API не было проблемой. И клиент (JavaScript/AJAX front-end) и сервер разворачивались одновременно. Потребители (ваши клиенты) всегда использовали самую последнюю версию клиентского ПО для доступа к системе.

Поскольку вы — единственная компания, разрабатывающая как клиентскую так и серверную часть, вы полностью контролируете то как используется ваш API и изменения в нем всегда сразу же применялись в клиентской части. К сожалению это невозможно с клиентскими приложениями, написанными под разные платформы.

Вы можете развернуть API версии 2, считая что все будет отлично, однако это приведет к неработоспособности приложений под iOS, использующих старую версию. Поскольку ещё могут быть пользователи, использующие такие приложения несмотря на то, что вы выложили обновленную версию в App Store.

Процесс приготовлений

Прежде чем приступить, мы продумали, что будем писать, как и даже накидали прототипы и макеты. После чего распланировали первый спринт в

. Таски иногда пополняются, но в на данный момент первый спринт выглядит так:

Видео. Пишем полноценное клиент-сервер приложение под Android / Хабр

Работа с сетью в android: трафик, безопасность и батарейка

На сегодняшний день в Google Play насчитывается более 800 тысяч приложений. Многие из них реализованы на основе клиент-серверного общения. При разработке таких приложений нужно учесть три основных момента, о которых пойдет речь в этой статье.

О чем нужно помнить при реализации сетевой части приложения

Первое – это трафик. Не всегда есть возможность работать по бесплатному Wi-Fi-соединению, а мобильный интернет всё еще дорогой, и об этом нужно помнить, потому что трафик – это деньги пользователя.

Второе – это лимит батарейки. Мобильные устройства необходимы пользователю для каких-то повседневных дел, совещаний, прогулок, бизнеса, и когда батарейка садится в самый неподходящий момент, пользователь негодует.
Третье – это безопасность. Так как все-таки речь идет о мобильных клиентах, и данные гуляют по сети от клиента к серверу и обратно, то их необходимо защищать.

Подходы по реализации сетевого взаимодействия

Для начала вспомним, какие способы реализации клиент-серверного общения существуют и популярны на сегодняшний день.
Первый подход — на основе сокетов (здесь я имею в виду работу непосредственно с Socket API). Он часто используется в приложениях, где важна скорость доставки сообщения, важен порядок доставки сообщений и необходимо держать стабильное соединение с сервером. Такой способ зачастую реализуется в мессенджерах и играх.

Видео. Пишем полноценное клиент-сервер приложение под Android / Хабр

Второй подход — это частые опросы (polling): клиент посылает запрос на сервер и говорит ему: «Дай мне свежие данные»; сервер отвечает на запрос клиента и отдает все, что у него накопилось к этому моменту.

Видео. Пишем полноценное клиент-сервер приложение под Android / Хабр

Минус такого подхода в том, что клиент не знает, появились ли свежие данные на сервере. По сети лишний раз гоняется трафик, в первую очередь из-за частых установок соединений с сервером.

Третий подход — длинные опросы (long polling) — заключается в том, что клиент посылает «ожидающий» запрос на сервер. Сервер смотрит, есть ли свежие данные для клиента, если их нет, то он держит соединение с клиентом до тех пор, пока эти данные не появятся. Как только данные появились, он «пушит» их обратно клиенту. Клиент, получив данные от сервера, тут же посылает следующий «ожидающий» запрос и т.д.

Видео. Пишем полноценное клиент-сервер приложение под Android / Хабр

Реализация этого подхода достаточно сложна на мобильном клиенте в первую очередь из-за нестабильности мобильного соединения. Зато при этом подходе трафика расходуется меньше, чем при обычном polling’e, т.к. сокращается количество установок соединений с сервером.
Механизм long polling, или пуш-уведомлений (push notifications), реализован в самой платформе Android. И, наверное, для большинства задач будет лучше использовать его, а не реализовывать самим. Ваше приложение подписывается у сервиса Google Cloud Messaging (GCM) на получение пуш-уведомлений.

Видео. Пишем полноценное клиент-сервер приложение под Android / Хабр

Тем самым разрывается связь непосредственно между сервером и клиентом за счет того, что сервер работает с сервисом GCM и отправляет свежие данные всегда на этот сервис, а он уже в свою очередь реализует всю логику доставки этих данных до вашего приложения. Плюсы этого подхода в том, что устраняется необходимость частых установок соединения с сервером за счет того, что вы точно знаете, что данные появились, и об этом вас оповещает сервис GCM.
Из этих четырех подходов наиболее популярными при разработке бизнес-приложений являются пуш-уведомления и частые опросы. При реализации этих подходов нам так или иначе придется устанавливать соединение с сервером и передавать данные. Далее речь пойдет об инструментах, которые есть в наличии у разработчика для работы по HTTP/HTTPS-протоколам.

HttpUrlConnection и HttpClient

В арсенале Android-разработчика есть два класса для работы по этим протоколам. Первый – это java.net.HttpURLConnection, второй – org.apache.http.client.HttpClient. Обе эти библиотеки включены в Android SDK. Далее будут подробно рассмотрены основные моменты, которые будут влиять на трафик, батарею и безопасность при работе с каждой из этих библиотек.

С HttpURLConnection все просто. Один класс и все. Это объясняется тем, что родительский класс URLConnection был спроектирован для работы не только по HTTP-протоколу, а еще по таким, как file, mailto, ftp и т.п.

Видео. Пишем полноценное клиент-сервер приложение под Android / Хабр

HttpClient спроектирован более объектно-ориентированно. В нем есть четкое разделение абстракций. В самом простом случае мы будем работать с пятью разными интерфейсами: HttpRequest, HttpResponse, HttpEntity и HttpContext. Поэтому апачевский клиент намного тяжеловеснее HttpUrlConnection.

Видео. Пишем полноценное клиент-сервер приложение под Android / Хабр

Как правило, на все приложение существует всего один экземпляр класса HttpClient. Это обусловлено его тяжеловесностью. Использование отдельного экземпляра на каждый запрос будет расточительным. Мы можем, к примеру, хранить экземпляр HTTP-клиента в наследнике класса Application.

Видео. Пишем полноценное клиент-сервер приложение под Android / Хабр

В случае HttpUrlConnection следует создавать на каждый запрос новый экземпляр клиента.

Видео. Пишем полноценное клиент-сервер приложение под Android / Хабр

Из чего складывается трафик?

Во время работы нашего приложения картинка будет примерно такая.

Видео. Пишем полноценное клиент-сервер приложение под Android / Хабр

Количество и частота запросов будет зависеть от функционала и насыщенности UI – интерфейса приложения. Каждый такой запрос устанавливает TCP-соединение с сервером. В данном случае трафик, который будет потрачен, будет равняться сумме установок соединений и сумме переданных данных. Понизить расход трафика в данном случае можно за счет использования долгоживущего соединения (keep alive).

Видео. Пишем полноценное клиент-сервер приложение под Android / Хабр

Основная идея keep alive-соединения заключается в использовании одного и то же TCP-соединения для отправки и приема HTTP-запросов. Главные преимущества — снижение трафика и времени выполнения запроса. Мной был проделан простенький тест, который заключался в том, что выполнялось последовательно 10 запросов на один и тот же хост. Данные представлены в таблице ниже. При выключенном keep alive видно, что среднее время выполнения запроса составляло примерно две секунды. В случае с включенным keep alive это время снизилось до 1,7 секунды, что на 16% быстрее. Это обуславливается в первую очередь тем, что устраняется необходимость частой установки соединения с сервером. При использовании защищенного HTTPS-соединения разница была бы заметнее, т.к. процедура SSL Handshake гораздо тяжелее процедуры TCP Handshake.

Видео. Пишем полноценное клиент-сервер приложение под Android / Хабр

Важным параметром keep alive-cоединения является keep alive duration. Он означает временной интервал. Если приходит несколько HTTP-запросов в пределах этого интервала, то будет переиспользоваться уже установленное TCP-соединение.

Видео. Пишем полноценное клиент-сервер приложение под Android / Хабр

Из рисунка видно, что время между четвертым и третьим запросом превысило keep alive duration, поэтому создается новое TCP-соединение с сервером.
Давайте посмотрим, как можно настроить вышеописанный параметр. В случае HttpClient все хорошо, в нашем распоряжении есть интерфейс ConnectionKeepAliveStrategy. Переопределив метод getKeepAliveDuration, мы можем вернуть нужное значение параметра keep alive duration.

httpClient.setKeepAliveStrategy(
  new ConnectionKeepAliveStrategy() {
    @Override
    public long getKeepAliveDuration(
                    HttpResponse response,                          		     		HttpContext context) {
      return KEEP_ALIVE_DURATION_MILLISECONDS;
    }
  });

Работая с HttpUrlConnection, нужно помнить о баге в платформе Android 2.2 и отключать keep alive на платформах <= 2.2.

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO) {
  System.setProperty("http.keepAlive", "false");
}

Второй неприятный (может быть, только для меня) момент при работе с HttpUrlConnection заключается в том, что параметр keep alive duration не поддается настройке (я легального способа не нашел, если кто подскажет — буду признателен). По умолчанию он примерно равен 5 секундам.

Также при работе с keep alive-соединением необходимо стараться вычитывать данные полностью из установленного соединения (коннекшена). Если не донца вычитывать данные, то можно получить коннекшены, которые буду висеть в пуле и «думать», что их еще кто-то собирается читать. Если InputStream успешно получен, читайте тело ответа полностью.

Полное вычитывание очищает коннекшн

от данных, и этот коннекшн будет переиспользован с большей вероятностью.

Работа с кукой (cookie)

Кука — небольшой фрагмент данных, отправленный веб-сервером и хранимый на компьютере пользователя. В нашем случае компьютером является Android-устройство. На практике куки обычно используются для аутентификации пользователя, хранения его персональных предпочтений и настроек, отслеживания состояния сессии доступа пользователя, ведения статистики о пользователях. Большое количество сервисов начинает разрабатывать мобильные приложения после того, как уже сделана мобильная версия сайта. В такой ситуации интересен вопрос: «Можно ли, получив авторизационную куку в мобильном приложении, установить ее в браузер (в WebView)?». При решении такой задачи есть пара деталей, которые помогут сэкономить ваше время:

  1. На плафтормах >= 4.0.3 (API Level 15) должна стоять точка в начале домена
  2. После вызова метода sync() у CookieSyncManager кука проставится только в WebView внутри вашего приложения, а в браузере — нет. Это ограничение накладывает система Android в целях безопасности

Видео. Пишем полноценное клиент-сервер приложение под Android / Хабр

Защищенное соединение (HTTPS)

В завершение данной статьи я рассмотрю, как включить HTTPS в Android. Насколько мне известно, на других мобильных платформах достаточно включить HTTPS-схему, механизм транспорта SSL — и все должно работать. В Android есть некоторые проблемы, которые следует учитывать и решать. Для начала вспомним, как устанавливается защищенное соединение. На проблемное место указывает красная стрелка – это проверка подлинности сертификата.

Видео. Пишем полноценное клиент-сервер приложение под Android / Хабр

На платформах < Android 4.0 при попытке выполнить сетевой запрос по HTTPS вылетит SSLHandshakeException. Возможность установить доверенный сертификат появилась на Android 4.0 с помощью KeyChain API. Но как быть с платформами ниже 4.0? На этих плаформах у нас остается два пути:

  1. Создавать локальное хранилище сертификатов
  2. Доверять любым сертификатам. В этом случае трафик тоже будет шифроваться, но угроза атаки man in the middle останется

Если выбор пал на создание локального хранилища сертификатов, то после того как оно будет создано, подключить его можно следующим образом:

— в случае HttpUrlConnection:

TrustManagerFactory tmf = 
      TrustManagerFactory.getInstance(algorithm);
KeyStore keyStore = KeyStore.getInstance("BKS");
InputStream in = 
      context.getResources().openRawResource(mykeystore);
keyStore.load(in, "mysecret".toCharArray());
in.close();
tmf.init(keyStore);
SSLContext sslc = SSLContext.getInstance("TLS");
sslc.init(null, tmf.getTrustManagers(),new SecureRandom());

— в случае HttpClient:

private SSLSocketFactory createSslSocketFactory() {
  SSLSocketFactory sf = null;
  try {
    KeyStore keyStore = KeyStore.getInstance("BKS");
    InputStream in = 
    context.getResources().openRawResource(mykeystore);
    keyStore.load(in, "mysecret".toCharArray());
    in.close();
    sf = new SSLSocketFactory(keyStore);
    sf.setHostnameVerifier(STRICT_HOSTNAME_VERIFIER);
  } catch (Exception e) {
    e.printStackTrace();
  }
  return sf;
}.

C помощью KeyStore.getInstance(«BKS») мы получаем объект KeyStore, который поддерживает Bounce Castle KeyStore format (Java-пакет для работы с крипто-алгоритмами). mykeystore – id ресурса, в котором лежат сертификаты.
mysecret – пароль от KeyStore. Более подробную информацию можно найти по ссылке на локальное хранилище сертификатов, приведенной выше.

Если же выбор пал на «Доверять любым сертификатом», то достаточно реализовать два интерфейса следующим образом:

private class DummyHostnameVerifier implements HostnameVerifier{
  
  @Override
  public boolean verify(String hostname, SSLSession session) {
    return true;
  }

}

private class DummyTrustManager implements X509TrustManager{

  @Override
  public void checkClientTrusted(...) throws CertificateException {
    //empty
  }

  @Override
  public void checkServerTrusted(...) throws CertificateException {
    //empty
  }
 ...
}

Затем следует применить эти реализации либо для HttpClient, либо для HttpUrlConnection.

А что с батарейкой?

Расход батареи напрямую зависит от количества устанавливаемых соединений с сервером, т.к. каждая установка активизирует беспроводное радио, которое расходует заряд батареи. О том, как работает беспроводное радио в Android и что влияет на расход батареи, рекомендую почитать в этой статье: Transferring Data Without Draining the Battery.

Прочитав статью, вы наверняка зададитесь вопросом, какой инструмент использовать — HttpClient или HttpUrlConnection? Разработчики платформы Android рекомендуют в новых приложениях использовать HttpUrlConnection, т.к. он прост в использовании, его будут развивать дальше и адаптировать под платформу. HttpClient следует использовать на платформах ниже Android 2.3, в первую очередь из-за серьезного бага с keep alive-соединением.

Эти три момента мы, конечно, учитываем и при разработке наших мобильных приложений. А о чем, в первую очередь, думаете вы?

Сетевой стек мобильного приложения

Чтобы оценить требования к сети, предъявляемые мобильным приложением рассмотрим интернет-магазин в качестве примера.

Базовые состояния приложения:

  • Пользователь авторизуется в приложении.
  • Пользователь находится на главной странице приложения.
  • Пользователь выбирает товар.
  • Пользователь добавляет товар в корзину.
  • Пользователь оформляет покупку.

Итоги

Возможно ли задействовать разработчиков клиентской части для создания бэкенда?

По очевидным причинам лидирующие позиции здесь занимают веб-разработчики и Node.js. Конечно, серверную часть делают и Flutter-разработчики. Dart позволяет писать сетевые серверные приложения, и, возможно, они удивят вас своей производительностью по сравнению с Node.js.

Скорее всего Flutter-разработчики будут не готовы к этим переменам, ввиду невостребованности такого использования языка Dart. Не хотелось бы рассматривать реализацию серверной части на Java по той же причине, а также из-за требовательности к ресурсам сервера и производительности системы ввода-вывода.

С точки зрения затрат и при отсутствии специализированных разработчиков в штате, идеальным решением было бы создание MVP на React-Native и серверной части на основе Node.js. Однако при отсутствии в штате веб-разработчиков лучшим решением, возможно, было бы использование Flutter в качестве основы.

Оценивая варианты сетевого взаимодействия мы, естественно, ориентировались на привычный для веб-разработчика стек протоколов.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *