В этой статье рассмотрим, что такое Instant App, зачем он нужен и как создать такое приложение?
Еще в прошлом году на DroidCon я слышал об этой теме. В этом году о ней тоже говорили. Наконец то у меня дошли руки посмотреть подробнее. В этой статье я расскажу, что мне удалось понять. Кода здесь практически не будет, только поверхностный разбор. И в конце несколько полезных ссылок для дальнейшего изучения.
Пример
Давайте сразу посмотрим пример. Есть такой видеохостинг - Vimeo. И у них есть свое Android приложение на маркете.
Если загуглить, например, "vimeo video", то гугл в результатах покажет несколько видео, нажав на которые можно перейти на Vimeo сайт. Т.е. браузер откроет ссылку вида https://vimeo.com/236370796. Но если делать это на Android смартфоне, на котором установлено Vimeo приложение, то оно и откроется вместо сайта. Система видит, что есть приложение, которое умеет открывать такую ссылку и запускает его.
Если же приложение Vimeo не установлено, то может открыться его Instant App версия.
Это приложение, которые мы даже явно не устанавливали. Система сама загрузила и установила его, и открыла в нем видео. (Не знаю почему рекордер не записал видео, которое проигрывается в верхней части экрана, но оно там есть). Обратите внимание также, что в этом приложении есть кнопка для перехода к установке полной версии с маркета.
Если у вас не запускается Instant App, то убедитесь, что он включен в настройках системы: Settings -> Google -> Instant App. Если у вас в настройках нет пункта Instant App, значит ваше устройство его не поддерживает.
Т.е. система перехватила ссылку, определила, что для нее есть Instant App приложение, скачала его и запустила. Ссылка играет очень важную роль в этой технологии. По сути URL - это точка входа (entry point) в приложение. Чуть позже я расскажу, как реализуется эта привязка.
А вот так выглядит полноценная версия приложения Vimeo, установленная с маркета.
Видно, что экраны обоих версий очень похожи, но у Instant App версии функционал ограничен. Instant App - это light версия основного приложения. Как мы уже видели, она может быть быстро подгружена и отображена при нажатии на ссылку.
Зачем нужен Instant App
Зачем это может понадобиться? Самый очевидный ответ - чтобы получить больше установок вашего приложения. Пользователь находит что-то в гугле (или просто получает ссылку в мессенджере, почте и т.п.), нажимает на ссылку и у него открывается ваше Instant App приложение. Оно позволяет пользователю увидеть примерный функционал и призывает установить полную версию. Тем самым вы получите нового пользователя. Т.е. Instant App - это классическая демоверсия приложения, которая помогает пользователю принять решение об установке полноценной версии.
Как создать Instant App приложение
Давайте разбираться, откуда взялась эта Instant App версия и как ее создать.
Создана она в том же самом проекте, что и основное приложение. Но чтобы была возможность создавать легковесную и ограниченную версию, необходимо разделить код основного приложения на модули.
О каких модулях речь? О тех самых, с которыми мы работаем в Android Studio. По умолчанию у нас создается только модуль app. Если мы работаем по Clean Architecture, то обычно создаем еще несколько модулей. А если мы собираемся создавать Instant App приложение, то мы выносим в модули отдельные фичи (features) приложения.
В примере с Vimeo такая фича - это экран просмотра видео. Т.е. в приложении есть какое-то Activity, которое отвечает за этот экран. Оно вынесено в отдельный модуль. Назовем этот модуль - videoplay. В этот модуль кроме Actiivty мы выносим используемые им классы - адаптеры, презентеры, кастомные вьюхи, и пр. Т.е. тут должны быть классы, которые нужны для работы только этому Activity и никому больше.
Для общеиспользуемых репозиториев и прочих классов, которые будут использоваться в модулях, предназначен отдельный модуль, который называется base.
В каждом feature-модуле прописана зависимость от base-модуля:
dependencies { implementation project(':base') ... }
Впрочем, это не мешает модулю base быть feature-модулем. Он также может содержать в себе Activity.
В итоге ваш проект состоит из одного base-модуля и нескольких feature-модулей. Из этого всего мы можем собрать два типа приложения.
Первое - это обычный полноценный APK, который включит в себя все ваши features-модули.
Второе - это ограниченное Instant App приложение, которое включит в себя base-модуль и те feature-модули, которые вы хотите видеть в этом приложении.
Чтобы обеспечить нам возможность собрать два разных приложения из одного кода, в Instant App проекте есть два модуля сборки: installed и instant.
installed соберет для нас полноценное приложение, а instant - Instant App версию.
В этих модулях есть gradle файлы, в которых мы прописываем feature-модули, который будут использованы при сборке приложения.
dependencies { implementation project(':base') implementation project(':feature1') implementation project(':feature2') }
Соответственно, в gradle файле модуля installed мы обычно указываем все feature-модули, чтобы получить APK с полным функционалом. А в gradle файле instant мы указываем только те features-модули, которые хотим видеть в Instant App приложении.
Модуль installed соберет APK, который будет использовать модули как библиотеки. А модуль instant сделает отдельный APK из каждого модуля и запакует все эти APK в один ZIP.
Маркет
Какую из этих двух версий приложения надо заливать на маркет?
Полноценный APK обязательно должен там быть. А вот Instant App - по вашему желанию. Если он вам нужен, то создавайте и заливайте.
Как программно определить версию
Т.к. обе версии приложения используют один и тот же код, то в этом коде может возникнуть необходимость проверять, в какой именно версии мы сейчас находимся. Для этого можно использовать метод isInstantApp.
Activity = модуль
И что, теперь нужно каждое Activity выносить в отдельный модуль?
Не нужно. Выносите в отдельные feature-модули только те экраны, который вы хотите видеть в Instant App. А весь остальной код можете оставить в одном отдельном feature-модуле, который просто не будет включен в Instant App. Не забудьте только в base-модуль поместить классы, которые нужны будут для работы feature-модулей.
URL
Я уже упоминал, что URL является входной точкой в Activity.
Каждый feature-модуль должен содержать в себе хотя бы одно Activity (можно и больше). И для этого Activity должен быть настроен IntentFilter на определенный URL.
Когда пользователь нажимает на ссылку, происходит следующее.
Система находит, что в маркете существует Instant App приложение, в котором есть feature-модуль, который умеет открывать такие ссылки.
Чуть выше я писал, что Instant App приложение представляет из себя ZIP, в котором собраны все feature-модули и base-модуль в виде отдельных APK. В случае с Vimeo, например, это могли бы быть, например, файлы videoplay.apk (создан из feature-модуля videoplay) и base.apk (создан из base-модуля). И в videoplay.apk есть Activity, для которого настроен IntentFilter на vimeo.com ссылки.
Система загружает videoplay.apk на устройство и запускает. Вместе с ним также она загружает base.apk. Т.е. когда идет первая загрузка какого-либо feature APK файла из Instant App, с ним вместе всегда грузится и base.apk. Потому что все feature зависимы от base. Отсюда, кстати, вытекает одно ограничение. Суммарный размер любого feature APK файла и base.apk не должен превышать 4 мегабайт. Т.е. в нашем случае суммарный размер файлов videoplay.apk и base.apk не должен превышать 4 MB. Это сделано, чтобы приложения Instant App были максимально легкими и быстро загружаемыми.
Тут важно понимать, что, даже если Instant App приложение содержит в себе еще какие-либо feature APK файлы, система загрузит только videoplay.apk (+ base.apk). Потому что в данный момент нужен только этот файл для обработки нажатой ссылки.
А что если экран из videoplay.apk предоставляет возможность перейти на какой-то другой экран, например, экран комментариев? В этом случае программно переход должен быть реализован не с помощью Intent, который вызывает Activity, а с помощью Intent, который вызывает ссылку. Например, это могла бы быть ссылка вида https://vimeo.com/236370796/comments.
Предположим, что в проекте есть feature-модуль videocomments, в котором находится Activity c IntentFilter, настроенным на такие ссылки. И этот feature-модуль был включен в список в модуле instant. В этом случае система найдет, что в Instant App приложении есть еще файл videocomments.apk, в котором есть Activity настроенное на этот тип ссылок. Система загрузит и запустит videocomments.apk. Файл base.apk в этом случае уже не будет загружаться, т.к. он был загружен ранее.
Try now
Если в маркете есть Instant App версия приложения, то пользователь видит кнопку Try now.
По нажатию этой кнопки происходит примерно то же самое, что и по нажатию на ссылку. Система загрузит один из feature APK вместе с base.apk и запустит его.
Какой именно модуль будет запущен, можно определить в манифесте. Будет найден тот APK, который содержит главное Activity. Т.е. Activity со стандартным фильтром:
<intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter>
Либо есть возможность в манифесте указать ссылку:
<meta-data android:name="default-url" android:value="https://vimeo.com/236370796" />
Она будет вызвана по нажатию на Try now и далее будет загружен и запущен соответствующий этой ссылке feature APK.
Полезные ссылки
Для дальнейшего изучения темы рекомендую посмотреть следующие материалы.
https://codelabs.developers.google.com/codelabs/android-instant-apps/index.html
и
https://codelabs.developers.google.com/codelabs/android-multi-feature-instant-app
Два codelab от google. В них вы увидите, как обычный проект можно переделать в Instant App. После этого вы будете понимать техническую сторону темы.
https://www.youtube.com/watch?v=tXqat1JOmS8 - видео с Google IO 18. Мало технических деталей, много общих слов про функционал и возможности. Полезно к просмотру, чтобы понять назначение этой технологии. Это видео можно скинуть продакт-менеджеру, чтобы он впечатлился и захотел внедрить такую штуку на проекте.
https://developer.android.com/topic/google-play-instant/faqs - FAQ с массой действительно интересных вопросов, которые возникают при изучении темы.
https://developer.android.com/topic/google-play-instant/best-practices/apps - Best Practices по функционалу, навигации и поведению Instant App приложений.
https://android-developers.googleblog.com/2017/08/android-instant-apps-best-practices-for.html - Best Practices по технической части создания Instant App приложения
Присоединяйтесь к нам в Telegram:
- в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
- в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Compose, Kotlin, RxJava, Dagger, Тестирование, Performance
- ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня