веб вью про что это
Зачем Android нужен WebView и как он работает
Несмотря на то что почти все смартфоны на Android получают новые версии ОС только два года, Google худо-бедно старается их поддерживать в актуальном состоянии ещё какое-то время путём обновления своих сервисов. Для этого поисковый гигант просто рассылает апдейты через Google Play, чтобы те пользователи, которым уже не светят традиционные обновления, могли получить запланированные нововведения и экстренные баг-фиксы. Однако, многие, как показала практика, этого не знают, и, видя, как системные компоненты с непонятными им названиями, спрашивают, например, что такое WebView и зачем это нужно. Восполняю пробел.
Вы много раз видели Android System WebView, но наверняка не знаете, что это и зачем нужно
Вы могли видеть WebView, полное название которого Android System WebView, в двух местах: в каталоге Google Play и в разделе «Приложения». Причём мелькает он заметно чаще других, периодически получая обновления и фигурируя в описаниях обновлений стороннего софта, разработчики которого почему-то считают необходимым упомянуть его. Прямо-таки в каждой бочке затычка. Однако, если разобраться чуть глубже, всё становится на свои места.
Что такое Android WebView
WebView — это встроенный браузер для приложений
WebView – это системный компонент, или, проще говоря, приложение, которое отвечает за открытие веб-страниц в рамках других приложений. Думаю, вам не раз приходилось открывать ту или иную ссылку в мессенджере, социальной сети или клиенте электронной почте. Так вот, если вы заметили, почти всегда нажатие на ссылку приводит к тому, что она открывается в интерфейсе самого приложения, вместо того чтобы перенести вас в браузер. Таким образом разработчику проще отслеживать ваши действия, поскольку получить их из стороннего браузера у него не выйдет.
Google рассказала, что изменится в Google Chrome после обновления
Но поскольку Android System WebView является, по сути, самостоятельным компонентом, периодически пользователи сталкиваются с проблемами в его работоспособности. Одни уверяют, что WebView не работает, другие сообщают, что WebView не обновляется, а третьи – что WebView недоступен. Казалось бы, причины у этих проблем могут быть самые разные и, чтобы что-то советовать пользователям, которые с ними столкнулись, нужно хотя бы разузнать дополнительные подробности или по крайней мере худо-бедно разбираться в разработке приложений и особенностях функционирования системных компонентов. Но нет.
WebView и Google Chrome
В конце прошлого года Google интегрировала в Android System WebView компонент Chrome WebView. Проще говоря, компания просто сделала так, что теперь все ссылки в сторонних приложениях будут открываться в виджете Chrome, который будет встроен во все программы по умолчанию. Поисковый гигант объяснил это тем, что это позволяет снизить нагрузку на ресурсы устройства и облегчит эффективность обновления. Но, как показывает практика, это только лишний раз запутало пользователей, которые вообще перестали понимать, что им делать в случае возникновения проблем.
Samsung хочет, чтобы Chrome для Android получил поддержку расширений
А, между тем, всё очень просто. Несмотря на то что Android System WebView по-прежнему обновляется самостоятельно, он глубоко связан с Google Chrome. Поэтому, когда вы сталкиваетесь с перебоями в работе системного компонента, вам нужно не искать обновления для него, а установить апдейт браузера.
Как обновить Android WebView
Зачастую обновлять следует не Android System WebView, а Google Chrome
Chrome загружает процессор и жрёт зарядку? Google всё исправит
На первый взгляд, может показаться, что всё это глупости, и на самом деле обновления ничего не решают, но это не так. В прошлом Google неоднократно выпускала такие патчи, которые возвращали работоспособность системных компонентов, от которых во многом зависела и работа сторонних приложений. Последний такой случай произошёл в декабре прошлого года, когда из-за сбоя в Chrome пользователи лишились возможности открывать ссылки в приложениях, которые к Google не имеют никакого отношения. Поэтому не пренебрегайте обновлениями. Они выходят для вас.
Android WebView: актуальные проблемы и их решение
На прошедшей встрече AndroidDevs Meetup выступили несколько разработчиков из команды мессенджера ICQ. Мой доклад был посвящен Android WebView. Для всех, кто не смог приехать на встречу, публикую здесь статью по мотивам выступления. Пойду по верхам, крупными штрихами. Глубоких технических деталей и много кода давать не буду. Если вас заинтересуют подробности, по ссылке в конце поста можно скачать приложение, специально написанное в качестве иллюстрации, и все увидеть на примерах.
Что такое WebView?
WebView — это компонент платформы Android, который позволяет встраивать web-страницы в Android-приложения. По сути, это встраиваемый браузер. При помощи WebView примерно год назад мы решили создать ICQ Web API для интеграции web-приложений в наш мессенджер. Что представляет собой web-приложение? По сути, это HTML-страница, которая содержит JavaScript и работает внутри ICQ. Используя ICQ Web API, web-страницы через JavaScript могут отдавать ICQ разные команды, допустим, на отправку сообщений, открытие чата и т.п.
Вот как это выглядит в ICQ. Из пункта Applications можно перейти в список приложений. Это пока еще не WebView, чтобы попасть в него, нужно выбрать одно из приложений. Тогда мы переходим непосредственно в WebView, куда web-приложение загружается из сети.
Как это устроено технически? У WebView есть возможность определенным образом инжектировать Java код в JavaScript. JavaScript может вызывать код, который мы написали и предоставили ему. Это возможность, на которой и основан весь ICQ Web API.
Здесь показано, что внутри ICQ работает WebView, между ними есть инжектированный Java-класс, а в WebView загружаются приложения из сети.
Итак, JavaScript из WebView делает вызовы к Java-коду ICQ. Существует большое число различных вызовов, и в процессе разработки встретилось множество проблем, связанных с работой этого механизма, о которых я и расскажу далее.
Проблемы при работе с WebView
После старта загрузки обычно бывает нужно проконтролировать этот процесс: узнать, успешно ли прошла загрузка, были ли редиректы, отследить время загрузки и другие вещи. Также будет сказано о потоках, в которых работает JavaScript и вызовы в Java, о несоответствии типов Java и JavaScript, поведении Alerts в JavaScript и размерах передаваемых данных. Решение для этих проблем будет также описано дальше.
Основы WebView
В двух словах об основах WebView. Рассмотрим четыре строки кода:
Тут видно, что мы получаем WebView и загружаем в него сайт example.com, вызвав WebView.loadURL(). В Android есть два важных класса: WebViewClient и WebChromeClient, которые взаимодействуют с WebView. Зачем они нужны? WebViewClient требуется для того, чтобы контролировать процесс загрузки страницы, а WebChromeClient — чтобы взаимодействовать с этой страницей после того, как она успешно загружена. До завершения загрузки страницы работает WebViewClient, а после — WebChromeClient. Как видно в коде, для того чтобы взаимодействовать с WebView, нам нужно создать собственные инстансы этих классов и передать их в WebView. Далее WebView при определенных условиях вызывает разные методы, которые мы переопределили в наших инстансах, и так мы узнаем о событиях в системе.
Наиболее важные методы, которые WebView вызывает у созданных нами инстансов WebViewClient и WebChromeClient:
WebViewClient | WebChromeClient |
---|---|
onPageStarted() | openFileChooser(), onShowFileChooser() |
shouldOverrideUrlLoading() | onShowCustomView(), onHideCustomView() |
onPageFinished(), onReceivedError() | onJsAlert() |
О назначении всех этих методов буду рассказывать немного позднее, хотя из самих названий уже многое понятно.
Контроль загрузки страницы в WebView
После того, как мы отдали WebView команду на загрузку страницы, следующим шагом нужно узнать результат выполнения: загрузилась ли страница. С точки зрения официальной Android-документации, все просто. У нас есть метод WebViewClient.onPageStarted(), который вызывается, когда страница начинает загружаться. В случае редиректа вызывается WebViewClient.shouldOverrideUrlLoading(), если страница загрузилась — WebViewClient.onPageFinished(), если не загрузилась — WebViewClient.onReceivedError(). Все кажется логичным. Как это происходит на самом деле?
Инжектирование кода Java в JavaScript
Пример кода JavaScript:
Здесь показан пример инжектирования кода Java в JavaScript. Создается коротенький Java-класс MyJavaInterface, и у него есть один единственный метод getGreeting(). Обратите внимание, что этот метод помечен маркирующим интерфейсом @JavaScriptInterface — это важно. Вызывая метод WebView.addJavascriptInterface(), мы пробрасываем данный класс в WebView. Ниже мы видим, как к нему можно обращаться из JavaScript, вызвав test.getGreeting(). Важным моментом здесь является имя test, которое впоследствии в JavaScript будет использовано как объект, через который можно делать вызовы к нашему Java-коду.
Если мы поставим breakpoint на строку return «Hello JavaStript!» и посмотрим имя потока, в котором получен вызов, какой это будет поток? Это не UI-поток, а специальный поток Java Bridge. Следовательно, если при вызове каких-то методов Java мы хотим манипулировать с UI, то нам нужно позаботиться о том, чтобы эти операции передавались в UI-поток — использовать хэндлеры или любой другой способ.
Второй момент: Java Bridge поток нельзя блокировать, иначе JavaScript в WebView просто перестанет работать, и никакие действия пользователя не будут иметь отклика. Поэтому если нужно делать много работы, задачи нужно также отправлять в другие потоки или сервисы.
Несоответствие типов Java в JavaScript
С передачей в обратную сторону, из JavaScript в Java, тоже есть нюансы. Если вызывать какой-то метод, имеющий параметрами элементарные типы, то можно передать туда number. А если среди параметров метода есть не элементарные типы, а скажем, объектные обертки, такие как Integer, то такой метод не будет вызван. Поэтому нужно пользоваться только элементарными типами Java.
Размеры данных, передаваемых между Java и JavaScript
Еще одна существенная проблема связана с объемом передаваемых данных между Java и JavaScript. Если передается достаточно большой объем данных (например, картинки) из JavaScript в Java, то при возникновении ошибки OutОfMemory, поймать ее не получится. Приложение просто падает. Вот пример того, что можно увидеть в logcat в этом случае:
Как видите, если в приложении происходит OutOfMemory, то начинают вылетать различные другие приложения, запущенные на устройстве. В итоге, закрыв все что можно, Android доходит до нашего приложения, и, так как оно находится в foreground, закрывает его последним. Еще раз хочу напомнить, что никакого исключения мы не получим, приложение просто упадет. Чтобы этого не происходило, необходимо ограничивать размер передаваемых данных. Многое зависит от устройства. На некоторых гаджетах получается передавать 6 мегабайт, на некоторых 2-3. Для себя мы выбрали ограничение в 1 мегабайт, и этого достаточно для большинства устройств. Если нужно передать больше, то данные придется резать на чанки и передавать частями.
JavaScript Alerts
По умолчанию диалог Alert в WebView не работает. Если загрузить туда страницу HTML с JavaScript и выполнить alert(‘Hello’), то ничего не произойдет. Чтобы заставить его работать, нужно определить свой инстанс WebChromeClient, переопределить метод WebChromeClient.onJSAlert() и в нем вызвать у него super.onJSAlert(). Этого достаточно, чтобы Alerts заработали.
Обработка изменения ориентации устройства
Ещё одна серьезная проблема связана с портретной и альбомной ориентацией. Если поменять ориентацию устройства, то по умолчанию Activity будет пересоздана. При этом все View, которые к ней прикреплены, тоже будут пересозданы. Представьте ситуацию: есть WebView, в который загружена некая игра. Пользователь доходит до 99 уровня, поворачивает устройство, и инстанс WebView с игрой пересоздается, страница загружается заново, и он снова на первом уровне. Чтобы этого избежать, мы используем мануальную обработку смены конфигурации устройства. В принципе, это вещь известная и описана в официальной документации. Для этого достаточно прописать в AndroidManifest.xml в разделе активити параметр configChanges.
Это будет означать, что мы сами обрабатываем смену ориентации в activity. Если ориентация изменится, мы получаем вызов Activity.onConfigurationChange() и можем поменять какие-то ресурсы программно. Но обычно activity с WebView имеют только сам WebView, растянутый на весь экран, и там ничего делать не приходится. Он просто перерисовывается и все продолжает нормально работать. Таким образом, установка configChanges позволяет не пересоздавать Activity, и все View, которые в нем присутствуют, сохранят свое состояние.
Полноэкранный медиаплеер
Если в web-страницу встроен медиаплеер, то часто возникает потребность обеспечить возможность его работы в полноэкранном режиме. Например, медиаплеер youtube может работать внутри web-страницы в html-теге iframe, и у него есть кнопка переключения в полноэкранный режим. К сожалению, в WebView по умолчанию это не работает. Чтобы заставить это работать, нужно сделать несколько манипуляций. В xml layout, в котором расположен WebView, разместим дополнительно FrameLayout. Это контейнер, который растянут на весь экран и в котором будет находится View с плеером:
А затем в своем инстансе WebChromeClient переопределим несколько методов:
Система вызывает WebChromeClient.onShowCustomView(), когда юзер нажимает на кнопку перехода в полноэкранный режим в плеере. оnShowCustomView() принимает View, которое и репрезентует сам плеер. Этот View вставляется в FullScreenContainer и делается видимым, а WebView скрывается. Когда пользователь хочет вернуться из полноэкранного режима, вызывается метод WebChromeClient.onHideCustimView() и проделывается обратная операция: отображаем WebView и скрываем FullScreenContainer.
Input type=”file”
Web-разработчики знают, что этот контейнер используется на web-страницах для того, чтобы пользователь мог выбрать какой-то файл и загрузить его на сервер, либо показать на экране. Для работы этого контейнера в WebView нам нужно переопределить метод WebChromeClient.openFileChooser(). В этом методе есть некий callback, в который нужно передать файл, выбранный пользователем. Никакого дополнительного функционала сам по себе /> не имеет. Диалог выбора файла нам нужно обеспечить. То есть мы можем открыть любой стандартный Android picker, в котором пользователь выберет нужный файл, получить его, например, через onActivityResult(), и передать в callback метода openFileChooser().
Пример кода JavaScript:
Определение состояния сети в JavaScript
В JavaScript есть полезный объект Navigator. У него есть поле onLine, показывающее статус сетевого подключения. Если у нас есть подключение к сети, в браузере это поле имеет значение true, в противном случае — false. Чтобы оно работало корректно внутри WebView, необходимо использовать метод WebView.setNetworkAvailable(). С его помощью мы передаем актуальное сетевое состояние, которое можно получить при помощи сетевого broadcast receiver или любым другим способом, которым вы трекаете сетевое состояние в Android. Делать это нужно постоянно. Если сетевое состояние изменилось, то нужно заново вызвать WebView.setNetworkAvailable() и передать актуальные данные. В JavaScript мы будем получать актуальное значение этого свойства через Navigator.onLine.
Примеры кода
Вопросы и ответы
Вопрос: Есть проект CrossWalk — это сторонняя реализация WebView, позволяющая на старых устройствах использовать свежий Chrome. У вас есть какой-то опыт, вы пробовали его встраивать?
Ответ: Я не пробовал. На текущий момент мы поддерживаем Android начиная с 14-й версии и уже не ориентируемся на старые устройства.
Вопрос: Как вы боретесь с артефактами, которые остаются при прорисовке WebView?
Ответ: Мы с ними не боремся, пробовали — не получилось. Это происходит не на всех устройствах. Решили, что это не настолько вопиющая проблема, чтобы тратить на нее больше ресурсов.
Вопрос: Иногда требуется WebView вложить в ScrollView. Это некрасиво, но иногда требуется по заданию. Это не поощряется, даже где-то запрещается, и после этого возникают недостатки в работе. Но все равно иногда это приходится делать. Например, если вы сверху рисуете WebView, а под ним рисуете какой-то нативный компонент (который должен быть нативным согласно требованию), и все это должно быть выполнено в виде единого ScrollView. То есть сначала пользователь посмотрел бы всю страничку, а потом, если бы захотел, то долистал бы до этих нативных компонентов.
Ответ: К сожалению, не могу вам ответить, потому что я не сталкивался с такой ситуацией. Она довольно специфическая, и представить себе вариант, когда нужно WebView положить в ScrollView, мне сложно.
Вопрос: Есть почтовое приложение. Там сверху шапка с получателями и со всем остальным. Даже в этом случае не все будет гладко. У WebView возникают большие проблемы, когда он пытается определить свой размер внутри ScrollView.
Ответ: Можно попробовать отрисовать означенную часть UI внутри WebView.
Вопрос: То есть полностью перенести всю логику из нативной части в WebView и оставить эти контейнеры?
Ответ: Даже, может быть, логику переносить не надо, имеется в виду инжектирование Java-классов. Логику можно оставить и вызывать через инжектированный класс. В WebView можно перенести только UI.
Вопрос: Вы упоминали про игры в мессенджере. Они представляют собой web-приложения?
Ответ: Да, это web-страницы с JavaScript внутри WebView.
Вопрос: Вы все это делаете, чтобы просто не переписывать игры нативно?
Ответ: И для этого тоже. Но основная идея в том, чтобы дать сторонним разработчикам возможность создавать приложения, которые могут встраиваться в ICQ, и с помощью этого ICQ Web API взаимодействовать с мессенджером.
Вопрос: То есть в эти игры можно играть также через web-браузер на лэптопе?
Ответ: Да. Она может быть открыта в web-браузере, и мы иногда их прямо в нем и отлаживаем.
Вопрос: А если Intent, допустим, в Chrome прокинуть эту игрушку, какие проблемы тогда будут? Если не свою WebView писать, а воспользоваться услугами?
Ответ: Проблема в том, что в своем WebView мы можем предоставить API через инжектирование Java-класса, и с помощью этого API приложение сможет напрямую взаимодействовать с ICQ, отправлять ему различные команды. Допустим, команду на получение имени пользователя, на получение чатов, которые у него открыты, отправлять сообщения в чат непосредственно из ICQ. То есть из Chrome отправлять сообщения непосредственно в ICQ не получится. В нашем случае все это возможно.
Вопрос: Вы упомянули, что режете данные на куски по одному мегабайту. Как вы их потом собираете?
Ответ: Мы сейчас этого не делаем, потому что у нас нет такой потребности.
Вопрос: Хватает одного мегабайта?
Ответ: Да. Если картинки больше, то пытаемся их ужимать. Я сказал о том, что если такая потребность существует, то это может быть решением — разрезать и собирать потом в Java.
Вопрос: Как вы обеспечиваете безопасность работы приложений в песочнице? Правильно ли я понял, что из JavaScript приложения нужно вызывать инжектированные Java-классы?
Ответ: Да.
Вопрос: Как будет обеспечиваться в этом случае безопасность, запрещен ли доступ к каким-то системным функциям?
Ответ: Прямо сейчас, так как система еще довольно молодая, у нас в основном используются наши собственные web-приложения, и мы им полностью доверяем. В дальнейшем все приложения, которые будут поступать к нам, будут администрироваться, код будет просматриваться, для этого выделена специальная Security Team. Дополнительно будет создана специальная система разрешений, без которых приложения не смогут получить доступ к какой-то критической для пользователя информации.
О WebView мобильных приложениях
Операционная система «Andriod» имеет встроенный компонент «WebView», позволяющий встраивать веб-страницы в мобильные приложения. На основе данной технологии осуществляется быстрая сборка гибридных Android-приложений, использующих в качестве источника контента мобильную версию сайта. Для полноценной реализации достаточно написать легкое нативное приложение с меню и подключить к нему сайт через компонент «WebView».
Для чего это нужно?! Различные предприятия и компании, выпуская какие-либо продукты или сервисы на рынок, выполняют реализацию сайта и мобильного приложения. Разработка нативного Android-приложения занимает много времени и связана с высокими издержками. Чтобы ускорить и удешевить процесс, имеет смысл реализовать «гибрид», который будет задействовать в работе страницы веб-сайта. Несмотря на ограниченный функционал и зависимость от интернета, подобного приложения бывает вполне достаточно для предварительного тестирования и оценки со стороны интернет-пользователей.
Какие преимущества и недостатки у «WebView» Android-приложений? Плюсами служит быстрая и дешевая реализация по сравнению с нативными продуктами. К минусам можно отнести зависимость от интернета, более долгая скорость загрузки контента, ограниченный функционал.
Отдельно можно выделить проблемы с безопасностью с точки зрения пользователя. Мобильные приложения на основе компонента «WebView» имеют доступ к конфиденциальной информации и персональным данным. Всегда возникает риск их недобросовестного использования и/или утечки.
Ранее, приложения на основе «WebView» можно было разрабатывать и для пользователей платформы «iOS», но компания «Apple» запретила их распространение в официальном магазине «AppStore». Таким образом, реализовать подобным образом iOS-приложение можно, но на следующей стадии возникнет проблема с его распространением.
Две стороны WebView: о быстром запуске проектов и краже персональных данных
Меня зовут Евгений, я Full Stack JS разработчик, текущий стек Node.js + React + React Native. В разработке я более 10 лет. В мобильной разработке пробовал разные инструменты от Cordova до React Native. Получив опыт работы с Cardova, я понял, что мне хотелось бы создавать нативные интерфейсы, на мой взгляд WebView не должно быть всем приложением. Но это не значит, что его не надо использовать вовсе.
По приглашению коллег из Сбербанка, в этом посте хочу рассказать про гибридные мобильные приложения. При правильном подходе, это отличный способ быстро реализовать идею в виде хорошо работающего продукта, достаточного для первого запуска вашего стартапа.
Источник: srishta.com
Также немного расскажу о том, как вы можете использовать WebView и как его могут использовать против вас злоумышленники. Примеры в статье будут показаны с использованием фреймворка React Native, но те же идеи можно реализовать и без него.
Немного про стартапы
Начну с принципиальных отличий в запуске стартапов у нас и на Западе, расскажу, как здесь может помочь WebView, дам рабочие примеры взаимодействия веб и нативных элементов, а также советы по технике безопасности при взаимодействии со сторонними приложениями.
Как правило, чтобы стартап стал успешным, ему нужно быстро запуститься. Потеряешь время – и конкуренты тебя обойдут. Это понимают и у нас, и на Западе. Но российский подход к запуску, как правило, гораздо основательнее — в плохом смысле этого слова.
Все неудачные российские стартапы начинаются и развиваются примерно по одному сценарию. Наиболее частые ошибки связаны со стратегическим планированием развития программного продукта. Руководство думает, что запуск возможен только после 110%-ной реализации всей функциональности и всех нюансов. При таком подходе быстро возникает дефицит бюджета, поскольку расходы на разработку высокие, а доходов от стартапа еще нет. Поиск дополнительных инвестиций, бесконечный круг утверждений и переработок занимает кучу времени, продукт появляется у конкурента. Все, марафон проигран.
Европейские и американские стартапы действуют иначе. Для начала они ограничиваются только мобильной веб-версией с минимально достаточной функциональной частью. Ее можно смотреть и с десктопов, и с мобильных устройств. И на этом этапе проект готов к запуску! После запуска для мобильных устройств делается приложение.
Как правило, по основным возможностям приложение не отличается от веб-версии. Оно расширяет возможности взаимодействия с пользователем, например посредствам пуш-уведомлений. Такой подход обеспечивает выполнение основного условия — быстрый запуск, быстрое получение первой прибыли. Доходы с первого этапа можно инвестировать в развитие. В дальнейшем проект может масштабироваться и развиваться как угодно без дефицита бюджета, бесконечно выполняя итерационный подход для добавления нового функционала и развития пользовательского интерфейса.
Предлагаю подробнее рассмотреть тот этап, когда уже есть мобильная версия сайта и нужно разрабатывать приложение для мобильных устройств. Итак, мы сделали сайт, а значит занимались разработкой серверного API, интерфейса и бизнес-логики. Два из трех компонентов –
— интерфейс и логика — присутствуют и в мобильном приложении. Согласитесь, не хочется писать их заново.
Объединяем лучшее от нативных и веб-приложений
Есть инструменты, ориентированные на разработку нативных приложений. Другие предназначены для веба. Преимущество нативных приложений в том, что они могут использовать весь функциональный потенциал телефона. Но разрабатывать их по сравнению с веб-приложениями довольно сложно. Веб дает возможность простого старта, но сильно ограничивает возможности приложения.
* для уменьшения тавтологии веб-приложениями я назову мобильные приложения, основная часть логики и интерфейса которых реализована на стороне браузера
Объединить все достоинства нативных приложений и веба позволяют гибридные приложения, которые создают с помощью компонента WebView. Конечно, найдутся дотошные разработчики, которые категорически против WebView в любых его проявлениях. Они аргументируют это тем, что приложение должно сразу быть полностью нативным, чтобы можно было использовать все возможности мобильного устройства, а также обеспечить комфортную производительность пользовательского интерфейса. Но во многих случаях, когда возможностей мобильной версии сайта вполне достаточно, можно сократить время первого запуска, сделав гибридное приложение, и заменять его на нативное постепенно.
Гибридные приложения — это не всегда что-то плохое и не расширяемое. Они могут быть удобными и производительными. При грамотном использовании такой подход помогает получить достаточное время на разработку качественного приложения, а не выпускать нативное приложение на скорую руку.
Есть несколько ситуаций, в которых целесообразно использовать гибридные приложения. Они хороши в качестве временной заглушки для быстрого старта — когда у нас готова мобильная версия сайта, а мобильное приложение нужно было «вчера». Такое приложение можно создать за несколько часов, запустить в продакшн. Пользователи получат возможность работать с мобильным приложением, а вы — возможность работать над более полноценной версией в менее жестких временных рамках (если это нужно).
Вот пример. Недавно коллегам срочно понадобилось мобильное приложение. В веб-версии у него было восемь пунктов меню, и мы их отобразили через WebView. А потом по одному пункту заменяли. Так получилось выпустить приложение не через месяц-три, а буквально за несколько дней. После постепенно переводили его на натив.
Гибридное решение не всегда временное. Его возможности позволяют переиспользовать в приложении кодовую базу, созданную ранее для веб-версии. К примеру специфичные анимации уже созданные на Canvas. Также WebView удобен, когда используется какой-то сторонний сервис. Еще один вариант – когда у вас есть сложный интерфейс, который проще подключить через WebView.
Как использовать WebView
Возьмем популярный сценарий. Мы хотим использовать мобильную версию сайта и нативное меню. Мы создаем нативное приложение с меню, но вместо контента подключаем мобильную версию сайта через WebView (пока что без каких либо изменений).
На гифке можно увидеть 2 меню. Правое меню является частью сайта, реализованное на веб, слева нативное меню, реализованное внутри мобильного приложения. Чтобы получить первое приближение к нативному приложению, нам достаточно просто скрыть то меню, которое реализовано на веб. Вот сколько кода нужно, чтобы через WebView отобразить веб-версию внутри приложения:
Следующий пример – о том, как нативная часть может взаимодействовать с вебом.
Робот нарисован на Canvas, это часть веб-сайта. А переключатель к нему построен на нативном UI. На разных телефонах он будет выглядеть по-разному. Мы можем управлять движениями робота при помощи переключателя. Можно и наоборот – какими-то элементами веб-интерфейса влиять на приложение. В React Native для этого предусмотрено специальный API для взаимодействия между вебом и нативной частью.
Ниже код для использования этой анимации. Layout — все пространство. Picker — нативная часть, которая может выбирать из dropdown варианты состояния робота. WebView — контейнер для отображения веба, внутри которого отрисовывается робот.
Подобные кейсы возникают часто. Например, мы сделали приложение для тестирования и аттестации стоматологов. Для каждого варианта ответа в тесте внутри вопросов рисовалась анимация, реализованная посредствам Canvas на вебе. Задача состояла в том, чтобы создать мобильное приложение, с этим тестированием. Использовав WebView, мы смогли отображать анимации из веба, тогда как остальной интерфейс мы построили нативно. Анимация отлично работала даже на старых смартфонах.
Как делаются инъекции
До 2013 года браузер Opera использовал собственный движок Presto, но потом его перевели на движок Blink от Google. Многих пользователей это очень расстроило. Свет на причины этого перехода проливает видео «Зачем опере вебкит». Главные виновники — большие корпорации типа Google или Facebook, которые не тестировали код своих продуктов в Opera и запрещали отображение страниц в этом браузере, ссылаясь на то, что он не достаточно популярен у пользователей.
Например, заходишь на Gmail через Opera и видишь: «Ошибка JavaScript». Пишешь в саппорт, получаешь ответ: «Opera у нас не поддерживается, мы не будем писать под нее код». Сначала компания Opera нанимала разработчиков, чтобы писать инъекции – специальный код, который встраивался в Gmail и позволял ему работать в Opera. Но постепенно таких сайтов, как Gmail, становилось все больше. Opera сдалась и сменила движок.
Так о чем это я? Ах да самое время поговорить об инъекциях:
На гифке – пример инъекции, которая изменяет поведение сайтов. Допустим, у нас есть чужой сайт, и мы делаем инъекцию стилей – скрываем правое меню и слайдер, выезжающий справа. Это – инъекция стилей. Логика работы сайта не меняется, только отображение.
Код, написанный зеленым, — инъекция. Она скрывает элементы, на них нельзя нажать, с ними нельзя взаимодействовать. С виду получается полностью нативное приложение, без веб-элементов управления.
Следующая инъекция интереснее. Допустим, у нас есть мобильное приложение, а в нем — встроенный мобильный браузер.
Человек переходит по ссылке, и мы запросто подставляем ему страничку Фейсбука, в которой нужно ввести логин и пароль. Если человек его вводит – приложение его перехватывает. Вот код:
Такой код называется инъекцией логики. Обычно он сложнее, но не намного. То есть утащить пароль проще, чем скрыть элементы управления.
Минутка паранойи: браузеры, встроенные в приложения
Как известно, во многих приложениях есть встроенные браузеры (WebView) — например, ВКонтакте, Telegram, Gmail, WhatsApp и так далее. Крупным компаниям мы можем доверять, но WebView используется и огромным количеством приложений с малым количеством звезд и сомнительными авторами — к примеру QR-ридерами, файловыми менеджерами, оболочками для камер и т.п… Устанавливаешь приложение, читаешь через него код, нажимаешь на ссылку, вводишь конфиденциальные данные — и у приложения, как показано в предыдущем примере, появляется доступ к ним. А потом уже не отследишь, куда эти данные утекают. Поэтому для открытия ссылок пользуйтесь только браузерами, которым доверяете.
Есть сайты, которые запрашивают логин и пароль каждый раз. А есть такие, которые делают это редко — раз в месяц, раз в год. Как ни странно, второй вариант безопаснее с точки зрения утечки данных через WebView. Например, ты заходишь на сайт с какого-то левого браузера. Сайт требует логин и пароль, и тебе не кажется это странным – он всегда так делает. А в случае, когда авторизация требуется редко, это заставит насторожиться.
Интересно, что двухфакторная авторизация от такой атаки не защищает – только от кражи пароля. Дело в том, что после подтверждения тебе в ответ возвращается токен, который, в свою очередь, двухфакторной авторизации уже не имеет, и его легко перехватить. То есть если ты ввел логин и код с СМС один раз, то браузер получает токен, который можно использовать многократно. С этим подтвержденным токеном он может делать что хочет, в течение времени, пока токен остается актуальным. В общем, не стоит слишком доверять встроенным браузерам.
Познакомиться с примерами из этого поста можно через демо-приложения. На ОС Android нужно скачать Expo Project — инструмент для работы с JavaScript и React Native. После установки Expo останется только считать QR-код:
С устройствами под iOS сложнее: компания Apple запретила распространять приложения таким образом. Так что любопытствующим придется собрать приложение из исходников на GitHub. Спасибо за внимание!