Ни для кого не секрет что смартфоны в наше время это вещь очень нужная и необходимая. Сейчас у каждого популярного сервиса есть своё мобильное приложение. Мобильное приложение полезно не только пользователю, но ещё и компании которая его предоставляет, ведь благодаря этому приложению можно увеличить охваты.

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

Когда я только брался за разработку, я не знал особо какие есть методы и на какой язык выбрать. Но в итоге мой первый выбор пал на React Native.

Нативные приложения

Когда я только начинал, я не знал, какие технологии лучше использовать. Я понимал, что не хочу разрабатывать два отдельных приложения — одно на Kotlin для Android, и второе на Swift для iOS. Это было бы слишком тяжело для одного человека, да и яблочных устройств для разработки на Swift у меня под рукой не было.

Мой выбор пал на React Native — JavaScript-фреймворк от Meta* (*организация, признанная экстремистской на территории РФ). Он позволяет писать один код для Android и iOS одновременно.

Звучит идеально, правда? На React Native работают такие крупные приложения, как Discord, Uber Eats, и даже различные приложения от Microsoft.

Но я быстро столкнулся с проблемами.

  • Тяжеловесность среды

    Даже банальные команды сборки могли сильно грузить систему. Часто приходилось ждать по несколько минут, пока приложение пересоберётся. Для мощных машин это не критично, но мой ноут явно не радовался. И ведь это я сделал только базовые функции по типу навигации.

  • Сложная отладка и документация

    Простой пример: я хотел настроить базу данных. Простая задача, казалось бы. Но оказалось, что прямое подключение серверной базы к приложению без промежуточного API не имеет смысла. Надо было использовать локальную базу данных (например, SQLite, потому что она легковесная и может работать офлайн) и синхронизировать ее с сервером, если есть интернет. Но понять, как это все работает в React Native, оказалось сложно. Мало актуальных гайдов, много недосказанностей, и куча багов при сборке.

  • Фронтенд заново

    Весь интерфейс нужно было воссоздавать с нуля. Сайт-то уже был, но повторить его логику и дизайн в мобильной версии оказалось куда сложнее, чем я думал.

    В итоге, я провёл почти полмесяца, пытаясь довести до ума базовую рабочую версию. И понял одну простую вещь:

    Для одного разработчика с ограниченным временем — нативная разработка на React Native не лучший путь.

Так или иначе а у React Native есть свои плюсы:

  • Кроссплатформенность - разработка под Android и iOS как и говорилось ранее.

  • Хорошая поддержка сообществом. Для React Native есть много разных библиотек которые упрощают работу и дают вам интересные функции в приложения.

  • Использование JavaScript. Этот язык является очень популярным на рынке, что снижает порог входа для веб-разработчиков и увеличивает востребованность специалистов.

    Я отложил проект на некоторое время.

Webview спешит на помощь

Я решил рассмотреть более простые реализации, которые мне бы позволили использовать уже готовый сайт для реализации. И такое решение нашлось - Webview.

WebView — это компонент, который позволяет отображать веб-контент (например, сайт) прямо внутри мобильного приложения. Такой подход часто используют новостные агрегаторы, интернет-магазины и даже крупные соцсети — там, где основной функционал уже реализован на вебе, и нет смысла дублировать всё нативно.

Разумеется, просто завернуть сайт в обёртку и выкатить в Google Play — плохая идея. Во-первых, модерация может не пропустить такое приложение. Во-вторых, нужно обеспечить минимальный уровень нативного UX: навигация, загрузочные экраны, работа оффлайн и т.п.

Для реализации WebView-приложения я выбрал Flutter — фреймворк от Google, построенный на языке Dart. Flutter оказался гораздо быстрее и стабильнее, чем React Native, особенно в плане сборки, зависимостей и документации.

Конкретно для WebView я использовал библиотеку flutter_inappwebview — она показалась мне самой гибкой и удобной.

Как всё устроено внутри

Приложение по сути отображает разные страницы сайта, но с нативной нижней навигацией, которая реагирует на текущий URL. Это позволяет пользователю ощущать себя внутри полноценного мобильного приложения, а не просто браузера.

Пример инициализации ссылок

В начале я определяю список URL-ов, каждый из которых соответствует определённой вкладке (здесь ссылки анонимизированы для примера):

final List<String> _urls = [
  'https://example.com/app/main',      // Главная
  'https://example.com/app/vocab',     // Словарь
  'https://example.com/app/grammar',   // Грамматика
  'https://example.com/app/practice',  // Практика
  'https://example.com/app/other',     // Прочее
];

Слежение за URL и смена вкладки

Когда пользователь переходит по ссылкам внутри WebView, приложение отслеживает текущий URL и меняет активную иконку в навигации. Для этого реализована простая функция:

void _updateCurrentIndex(String url) {
  final newIndex = () {
   if (url.contains('index.php')) return 0;
   if (url.contains('practice') || url.contains('prgrammar') || url.contains('prvocab')) return 3;
   if (url.contains('vocab')) return 1;
   if (url.contains('grammar')) return 2;
   return 4; // Прочее
  }();

  if (newIndex != _currentIndex) {
    setState(() {
      _currentIndex = newIndex;
    });
  }
}

Важно:
Используйте уникальные части URL для каждого раздела, чтобы не было пересечений между вкладками. А если пересечения и есть как у меня (prvocab и prgrammar), то стоит поднять такое условие выше чтобы у него был приоритет.

Открытие внешних ссылок

Чтобы внешние сайты и приложения открывались не внутри WebView, а во внешнем браузере или нужном приложении, я использовал пакет url_launcher:

shouldOverrideUrlLoading: (controller, navigationAction) async {
  final uri = navigationAction.request.url;

  if (uri == null) return NavigationActionPolicy.CANCEL;

  _updateCurrentIndex(uri.toString());

  // Открываем только свой сайт внутри приложения
  if (uri.host.contains('rushengl.com')) {
    return NavigationActionPolicy.ALLOW;
  }

  // Внешние ссылки — через браузер или другое приложение
  if (await canLaunchUrl(uri)) {
    await launchUrl(uri, mode: LaunchMode.externalApplication);
  }

  return NavigationActionPolicy.CANCEL;
}

canLaunchUrl и launchUrl — это асинхронные функции из пакета url_launcher. Они позволяют безопасно открывать внешние ссылки через браузер или другие приложения.

Важные настройки для Android

Чтобы приложение могло работать с интернетом, обязательно нужно добавить разрешения в файл AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

Без разрешения на интернет (INTERNET) WebView просто не сможет загрузить сайт.

Подведение итогов

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

Если бы я пошёл по пути полной нативной разработки, даже с React Native, мне бы потребовалось, скорее всего, пару месяцев минимум. А с WebView и Flutter я уложился в две недели, и получил рабочее, стабильное приложение, которое уже доступно в Google Play, RuStore и Huawei Market.

Разумеется, путь не был безболезненным. Я не знал Dart и активно использовал ИИ-помощников в разработке. Но это не значит, что я просто копировал чужой код. Я разбирался, читал, тестировал, исправлял баги. Иногда уходил целый день на то, чтобы понять, почему не работает банальная вещь — но оно того стоило.

Такой подход — не панацея. WebView не подойдёт, если вам нужно сложное, интерактивное приложение с кастомными анимациями, offline-хранилищем, или глубоким доступом к железу. Но если у вас уже есть сайт, и вы хотите завернуть его в мобильную упаковку — WebView может сэкономить вам месяцы работы.

Советы начинающим

Вот несколько советов тем, кто решит пойти по пути разработчика мобильного приложения впервые и в одиночку:

  • Не бойтесь использовать ИИ, но не полагайтесь на него вслепую. Часто он может усложнять простые вещи или выдавать устаревшие решения. Лучше прочитайте документацию и разберитесь сами в проблеме — может оказаться, что решение проще, чем казалось.

  • Сохраняйте разные версии проекта. Особенно важно разделять версию с ключом подписи (для публикации) и debug-версию (для разработки). Я однажды подписал основную сборку, и потом пришлось откатываться назад и переорганизовывать проект, чтобы снова собирать без подписи.

  • Не беритесь за тяжёлую артиллерию без надобности. Если вам не нужно сложное кастомное поведение — не усложняйте себе жизнь. Простые задачи требуют простых решений. Иногда WebView — это именно то, что нужно.

  • Добавьте нативный UX — навигацию, анимации, разрешения на использование чего-либо (если оно требуется), Splash Screen и прочее чтобы приложение точно прошло и выглядело как нативное для пользователя.

Flutter vs React Native — что выбрать?

Оба инструмента по-своему хороши, и каждый подходит под свои задачи:

Flutter

React Native

Язык

Dart

JavaScript

Скорость сборки

Быстрее

Могут быть долгие билды

Поддержка

Отличная от Google

Широкая, от Meta и сообщества

Документация

Современная и подробная

Иногда устаревшая или неполная

UI

Отрисовка с нуля (canvas)

Обёртка над нативными компонентами

Кроссплатформенность

Да

Да

Порог входа

Средний (нужно знать Dart)

Ниже (если знаете JS)

React Native отлично подойдёт, если вы уже знакомы с JavaScript или делаете сложное приложение с большим количеством нативных модулей и кастомной логикой. Его используют крупные компании (Discord, Microsoft, Uber и др.), и для сложных проектов с большим бюджетом и командой это оправдано.

Flutter — лучшее решение для быстрого и стабильного вывода веб-сайта в формате приложения, особенно если нужен WebView или кастомный UI. Он проще в поддержке, быстрее собирается и не требует глубоких знаний платформенных особенностей.

Заключение

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

Да, WebView — это не rocket science. Но если работает, выглядит достойно и даёт пользователю нормальный UX — почему бы и нет?

Комментарии (0)