Создание нескольких APK с несколькими измерениями

Если вы публикуете свое приложение в Google Play, вам необходимо создать и загрузить пакет Android App Bundle . Когда вы это сделаете, Google Play автоматически создаст и предоставит оптимизированные APK-файлы для конфигурации устройства каждого пользователя, поэтому они загружают только тот код и ресурсы, которые им необходимы для запуска вашего приложения. Публикация нескольких APK-файлов полезна, если вы не публикуете их в Google Play, но вам необходимо самостоятельно создавать, подписывать и управлять каждым APK-файлом.

При разработке приложения Android для использования нескольких APK-файлов в Google Play важно с самого начала принять некоторые передовые методы и избежать ненужных головных болей в дальнейшем процессе разработки. В этом уроке показано, как создать несколько APK-файлов вашего приложения, каждый из которых будет охватывать разные классы размеров экрана. Вы также получите некоторые инструменты, необходимые для того, чтобы максимально упростить поддержку нескольких кодовых баз APK.

Подтвердите, что вам нужно несколько APK

Пытаясь создать приложение, которое будет работать на огромном количестве доступных устройств Android, естественно, вы хотите, чтобы ваше приложение выглядело наилучшим образом на каждом отдельном устройстве. Вы хотите использовать пространство больших экранов, но при этом работать на маленьких, использовать новые функции Android API или визуальные текстуры, доступные на современных устройствах, но не отказываться от старых. Поначалу может показаться, что поддержка нескольких APK — лучшее решение, но зачастую это не так. Раздел «Использование одного APK вместо» руководства по использованию нескольких APK содержит полезную информацию о том, как выполнить все это с помощью одного APK, включая использование нашей библиотеки поддержки и ссылки на ресурсы в руководстве для разработчиков Android.

Если вы можете справиться с этим, ограничение вашего приложения одним APK-файлом имеет ряд преимуществ, в том числе:

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

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

Напишите свои требования

Начните с создания простой диаграммы, чтобы быстро определить, сколько APK вам нужно и какой размер экрана охватывает каждый APK. К счастью, ваши требования можно легко и быстро сформулировать и иметь под рукой справочную информацию на будущее. Допустим, вы хотите разделить APK-файлы по двум измерениям: API и размеру экрана. Создайте таблицу со строкой и столбцом для каждой возможной пары значений и раскрасьте несколько «каплей», каждый цвет представляет один APK.

3 4 5 6 7 8 9 10 11 12 +
маленький
нормальный
большой
большой

Выше приведен пример с четырьмя APK. Синий — для всех устройств с маленьким/обычным экраном, зеленый — для устройств с большим экраном, а красный — для устройств с большим экраном, все с диапазоном API 3–10. Фиолетовый — это особый случай, поскольку он подходит для всех размеров экрана, но только для API 11 и выше. Что еще более важно, просто взглянув на эту диаграмму, вы сразу узнаете, какой APK охватывает ту или иную комбинацию API/размера экрана. Вдобавок, у вас также есть шикарные кодовые имена для каждого из них, поскольку «Мы тестировали красный цвет на ?» Гораздо проще спросить своего кубика, чем «Протестировали ли мы APK-файл xlarge 3–10 с Xoom?» Распечатайте эту диаграмму и раздайте ее каждому, кто работает над вашей кодовой базой. Жизнь стала намного проще.

Поместите весь общий код и ресурсы в проект библиотеки.

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

Примечание. Подробности реализации создания и включения проектов библиотек выходят за рамки этого урока, но вы можете быстро освоиться, прочитав «Создание библиотеки Android» .

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

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

Создание новых проектов APK

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

alexlucas:~/code/multi-apks-root$ ls
foo-blue
foo-green
foo-lib
foo-purple
foo-red

После создания проектов добавьте проект библиотеки в качестве ссылки на каждый проект APK. Если возможно, определите начальное действие в проекте библиотеки и расширьте это действие в проекте APK. Наличие стартового действия, определенного в проекте библиотеки, дает вам возможность разместить всю инициализацию вашего приложения в одном месте, так что каждому отдельному APK не придется повторно реализовывать «универсальные» задачи, такие как инициализация Analytics, запуск проверок лицензии и любые другие. другие процедуры инициализации, которые не сильно меняются от APK к APK.

Настройте манифесты

Когда пользователь загружает приложение, использующее несколько APK-файлов, через Google Play, правильный APK-файл выбирается с использованием двух простых правил:

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

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

3 4 5 6 7 8 9 10 11 12 +
маленький
нормальный
большой
большой

Поскольку перекрытие покрытия вполне допустимо, мы можем описать область, охватываемую каждым APK, следующим образом:

  • Синий цвет охватывает все экраны, minSDK 3.
  • Зеленые обложки Большие экраны и выше, minSDK 3.
  • Красный цвет охватывает экраны XLarge (обычно планшеты), minSDK 9.
  • Фиолетовый цвет охватывает все экраны, minSDK — 11.

Обратите внимание, что эти правила во многом совпадают. Например, устройство XLarge с API 11 предположительно может запускать любой из 4 указанных APK. Однако, используя правило «выигрывает наибольший номер версии», мы можем установить следующий порядок предпочтения:

Фиолетовый ≥ Красный ≥ Зеленый ≥ Синий

Зачем допускать все дублирование? Давайте представим, что у Purple APK есть некоторые требования, которых нет у двух других. На странице «Фильтры в Google Play» руководства для разработчиков Android приведен целый список возможных виновников. Для примера предположим, что Purple требуется фронтальная камера. На самом деле, весь смысл Purple в том, чтобы использовать развлекательные штуки с помощью фронтальной камеры! Но, оказывается, не на всех устройствах с API 11+ ЕСТЬ даже фронтальная камера! Ужас!

К счастью, если пользователь просматривает Google Play с одного из таких устройств, Google Play просмотрит манифест, увидит, что Purple указывает наличие фронтальной камеры в качестве требования, и спокойно проигнорирует это, определив, что Purple и это устройство не являются матч, созданный на цифровом раю. Тогда он увидит, что Red не только совместим с устройствами xlarge, но его не волнует, есть ли фронтальная камера! Пользователь по-прежнему может загрузить приложение из Google Play, потому что, несмотря на всю неудачу с фронтальной камерой, все еще существовал APK, который поддерживал этот конкретный уровень API.

Чтобы все ваши APK-файлы находились на отдельных «дорожках», важно иметь хорошую схему кода версии. Рекомендуемый вариант можно найти в разделе «Коды версий» нашего руководства для разработчиков. Стоит прочитать весь раздел, но основная суть в том, что для этого набора APK мы будем использовать две цифры для обозначения minSDK, две для обозначения минимального/максимального размера экрана и 3 для обозначения номера сборки. Таким образом, когда устройство обновится до новой версии Android (скажем, с 10 до 11), любые APK, которые теперь подходят и предпочтительнее установленного в данный момент, будут восприниматься устройством как «обновление». Схема нумерации версий применительно к примеру набора APK может выглядеть так:

Синий: 0304001, 0304002, 0304003...
Зеленый: 0334001, 0334002, 0334003.
Красный: 0344001, 0344002, 0344003...
Фиолетовый: 1104001, 1104002, 1104003...

Если сложить все это вместе, ваши манифесты Android, скорее всего, будут выглядеть примерно так:

Синий:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionCode="0304001" android:versionName="1.0" package="com.example.foo">
    <uses-sdk android:minSdkVersion="3" />
    <supports-screens android:smallScreens="true"
        android:normalScreens="true"
        android:largeScreens="true"
        android:xlargeScreens="true" />
    ...

Зеленый:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionCode="0334001" android:versionName="1.0" package="com.example.foo">
    <uses-sdk android:minSdkVersion="3" />
    <supports-screens android:smallScreens="false"
        android:normalScreens="false"
        android:largeScreens="true"
        android:xlargeScreens="true" />
    ...

Красный:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionCode="0344001" android:versionName="1.0" package="com.example.foo">
    <uses-sdk android:minSdkVersion="3" />
    <supports-screens android:smallScreens="false"
        android:normalScreens="false"
        android:largeScreens="false"
        android:xlargeScreens="true" />
    ...

Фиолетовый:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionCode="1104001" android:versionName="1.0" package="com.example.foo">
    <uses-sdk android:minSdkVersion="11" />
    <supports-screens android:smallScreens="true"
        android:normalScreens="true"
        android:largeScreens="true"
        android:xlargeScreens="true" />
    ...

Обратите внимание, что технически несколько APK-файлов будут работать либо с тегом support-screens, либо с тегом совместимых экранов. Поддержка экранов, как правило, предпочтительнее, и, как правило, использовать оба — очень плохая идея. Это неоправданно усложняет задачу и увеличивает вероятность ошибок. Также обратите внимание, что вместо использования значений по умолчанию (маленький и нормальный всегда верны по умолчанию), манифесты явно устанавливают значение для каждого размера экрана. Это может избавить вас от головной боли в будущем. Например, в манифесте с целевым SDK <9 будет автоматически установлено значение xlarge равным false, поскольку такого размера еще не существовало. Так что будьте откровенны!

Просмотрите контрольный список перед запуском

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

  • Все APK-файлы должны иметь одно и то же имя пакета.
  • Все APK должны быть подписаны одним и тем же сертификатом.
  • Если APK-файлы совпадают по версии платформы, файл с более высоким значением minSdkVersion должен иметь более высокий код версии.
  • Для каждого размера экрана, который должен поддерживать APK, в манифесте установите значение true. Для каждого размера экрана, которого вы хотите избежать, установите значение false.
  • Дважды проверьте фильтры манифеста на предмет противоречивой информации (APK, который поддерживает только кексы на экранах XLARGE, никто не увидит).
  • Манифест каждого APK должен быть уникальным хотя бы для одной поддерживаемой версии экрана, текстуры OpenGL или версии платформы.
  • Попробуйте протестировать каждый APK хотя бы на одном устройстве. За исключением этого, на вашей машине разработки находится один из самых настраиваемых эмуляторов устройств в отрасли. С ума сойти!

Также стоит проверить скомпилированный APK перед выпуском на рынок, чтобы убедиться в отсутствии каких-либо сюрпризов, которые могут скрыть ваше приложение в Google Play. На самом деле это довольно просто с помощью инструмента «aapt». Aapt (инструмент упаковки ресурсов Android) — это часть процесса сборки для создания и упаковки ваших приложений Android, а также очень удобный инструмент для их проверки.

>aapt dump badging
package: name='com.example.hello' versionCode='1' versionName='1.0'
sdkVersion:'11'
uses-permission:'android.permission.SEND_SMS'
application-label:'Hello'
application-icon-120:'res/drawable-ldpi/icon.png'
application-icon-160:'res/drawable-mdpi/icon.png'
application-icon-240:'res/drawable-hdpi/icon.png'
application: label='Hello' icon='res/drawable-mdpi/icon.png'
launchable-activity: name='com.example.hello.HelloActivity'  label='Hello' icon=''
uses-feature:'android.hardware.telephony'
uses-feature:'android.hardware.touchscreen'
main
supports-screens: 'xlarge'
supports-any-density: 'true'
locales: '--_--'
densities: '120' '160' '240'

Когда вы проверяете выходные данные aapt, обязательно убедитесь, что у вас нет конфликтующих значений для support-screens и совместимых-screens, а также что у вас нет непреднамеренных значений «uses-feature», которые были добавлены в результате разрешений, которые вы установлен в манифесте. В приведенном выше примере APK будет невидим для большинства, если не для всех, устройств.

Почему? Добавление необходимого разрешения SEND_SMS неявно добавило требование к функции android.hardware.telephony. Поскольку большинство (если не все) устройств xlarge представляют собой планшеты без телефонного оборудования, Google Play в этих случаях будет отфильтровывать этот APK до тех пор, пока не появятся будущие устройства, которые будут достаточно большими, чтобы сообщать о размере экрана xlarge, и будут обладать телефонным оборудованием.

К счастью, это легко исправить, добавив в манифест следующее:

<uses-feature android:name="android.hardware.telephony" android:required="false" />

Требование android.hardware.touchscreen также добавляется неявно. Если вы хотите, чтобы ваш APK был виден на телевизорах без сенсорного экрана, вам следует добавить в свой манифест следующее:

<uses-feature android:name="android.hardware.touchscreen" android:required="false" />

Заполнив контрольный список перед запуском, загрузите APK-файлы в Google Play. Приложению может потребоваться некоторое время, чтобы оно появилось при просмотре Google Play, но когда это произойдет, выполните последнюю проверку. Загрузите приложение на любые тестовые устройства, которые вам могут понадобиться, чтобы убедиться, что APK-файлы предназначены для нужных устройств. Поздравляем, все готово!