Вы сделали PWA — оно работает в браузере, стоит на домашний экран, работает офлайн. Теперь хочется поставить его в Play Store, чтобы пользователи находили приложение привычным способом. Только вот писать всё заново на Kotlin не хочется. Хорошая новость: не нужно. Под Android есть два способа завернуть веб в приложение без переписывания с нуля. Разберём оба.
Три варианта показать веб в Android-приложении
Прежде чем выбирать, полезно понять из чего выбирать.
Custom Tabs — это когда Android-приложение открывает страницу во встроенном Chrome, который стилизован под ваше приложение. Адресная строка видна, ощущение браузерное. Хорошо подходит для открытия внешних страниц — например, экрана входа через OAuth. Для упаковки всего приложения не годится.
TWA (Trusted Web Activity) — надстройка над Custom Tabs. Тот же Chrome пользователя, но без адресной строки, на весь экран. Внешне неотличимо от нативного приложения. Под капотом крутится ваш PWA по настоящему URL. Минимум кода, крошечный пакет.
Capacitor — совсем другой подход. Это обёртка, которая упаковывает ваши файлы прямо в пакет приложения и показывает их через системный WebView устройства. Движок — не Chrome пользователя, а компонент WebView, встроенный в Android. Зато JS-мост даёт доступ к камере, файловой системе, push-уведомлениям и другим возможностям платформы.
Для большинства задач выбор стоит между TWA и Capacitor.
Что такое TWA и зачем нужна «доверенность»
Trusted Web Activity — это Android-активность, которая запускает Chrome в полноэкранном режиме. Пользователь видит ваше приложение, но под капотом это Chrome без адресной строки.
Слово «Trusted» здесь принципиальное. Без проверки любое приложение могло бы показать любой сайт и выдать его за свой — например, фишинговый банк в оболочке приложения. Чтобы этого не было, Android требует доказательства: приложение должно подтвердить, что домен действительно ему принадлежит. Если проверка не пройдёт — адресная строка вернётся, и пользователь поймёт, что что-то не так.
Само доказательство называется Digital Asset Links — о нём ниже.
Два практических следствия TWA:
- Маленький пакет. Движок не едет вместе с приложением — это Chrome, уже стоящий на телефоне. Пакет TWA-приложения весит десятки килобайт.
- Актуальный движок. Пользователь видит ваш сайт в той версии Chrome, что обновилась на его телефоне. Не нужно ждать, когда производитель устройства обновит системный WebView.
Как собрать TWA через Bubblewrap
TWA-проект не пишут руками — его генерирует Bubblewrap, инструмент командной строки от Google Chrome Labs.
npm install -g @bubblewrap/cli
bubblewrap init --manifest https://example.com/manifest.webmanifest
bubblewrap build
init читает ваш веб-манифест: берёт оттуда название, иконки, цвет темы, стартовый URL — и задаёт только те вопросы, которые не смог вывести сам. build подписывает пакет ключом и отдаёт два файла:
app-release-signed.apk— для установки на устройство напрямую во время разработкиapp-release-bundle.aab— для загрузки в Play Store
Если не хочется устанавливать инструменты локально — есть PWABuilder: указываете URL вашего PWA в браузере, он генерирует готовый Android-пакет через то же TWA.
Как собрать приложение через Capacitor
Capacitor работает иначе: он создаёт полноценный нативный проект, куда копирует ваши собранные веб-файлы.
npm install @capacitor/android
npx cap add android
npx cap sync
npx cap open android
cap add android создаёт папку android/ с нативным проектом. cap sync копирует туда собранный веб. cap open android открывает проект в Android Studio, откуда и собирается финальный .aab.
Это и есть разница в подходах: TWA — две команды над живым URL, Capacitor — полноценный нативный проект, которым нужно управлять.
Capacitor выбирают, когда нужен доступ к возможностям платформы, которые веб-платформа ещё не поддерживает: Bluetooth, фоновая геолокация, нативные уведомления с богатым контентом.
Digital Asset Links: как подтвердить домен
Чтобы TWA убрало адресную строку, сайт должен публично заявить, что доверяет конкретному приложению. Делается это через файл /.well-known/assetlinks.json:
[
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "ru.example.app",
"sha256_cert_fingerprints": [
"AB:CD:EF:12:34:56:78:90:..."
]
}
}
]
package_name — идентификатор вашего Android-приложения. sha256_cert_fingerprints — отпечаток ключа подписи. Если вы используете Play App Signing (Google хранит ключ распространения), нужный отпечаток берётся в Play Console, раздел «Настройка» → «Подпись приложения».
Как проверить, что всё работает: запустите приложение на устройстве. Если адресная строка исчезла — проверка прошла. Если осталась — файл недоступен или отпечаток не совпадает.
Публикация в Play Store
С 2021 года Play Store принимает новые приложения только в формате Android App Bundle — файл с расширением .aab. Это не APK. Принцип другой: вы загружаете один бандл, Google сам нарезает из него оптимизированные APK для каждой конфигурации устройства. Пользователь скачивает меньше.
Путь до публикации одинаков для TWA и Capacitor:
- Создать приложение в Play Console.
- Загрузить
.aab. - Заполнить карточку приложения (описание, скриншоты, категория).
- Дождаться проверки — обычно несколько дней.
Разница только в источнике бандла: у TWA это файл от Bubblewrap, у Capacitor — сборка из Android Studio.
Коротко
- TWA показывает ваш PWA через Chrome пользователя — адресной строки нет, пакет крошечный, движок всегда свежий.
- Capacitor упаковывает веб-файлы внутрь приложения через системный WebView — больше нативного контроля, тяжелее поддержка.
- Bubblewrap генерирует TWA-проект из веб-манифеста за две команды. PWABuilder делает то же через браузер.
- Digital Asset Links — обязательный шаг для TWA: файл
/.well-known/assetlinks.jsonна сайте подтверждает, что вы владеете доменом, и убирает адресную строку. - В Play Store идёт
.aab, а не.apk. - Если
assetlinks.jsonнастроен неправильно или недоступен — адресная строка появится снова. Это первое, что проверять при отладке.
Что почитать дальше
- PWA: сервис-воркеры и офлайн — с чего начинается web-first приложение.
- Capacitor: нативные возможности — подробнее про JS-мост и доступ к API платформы.
- iOS и WKWebView — то же самое, но для App Store и Apple.