При включении оптимизации приложений поведение оптимизатора по умолчанию различается для разных версий R8.
- В обновленном DSL, доступном начиная с AGP 9.3 и более поздних версий , уменьшение объема ресурсов включено по умолчанию при включении оптимизации. Обратите внимание, что устаревший DSL, требующий отдельного включения оптимизации кода и ресурсов, по-прежнему поддерживается.
Для версий AGP до 9.3 параметр
isShrinkResources = trueуказывает оптимизатору удалять неиспользуемые ресурсы, что помогает уменьшить размер вашего приложения. Сжатие ресурсов работает только в сочетании со сжатием кода, поэтому, если вы оптимизируете ресурсы, также установите параметрisMinifyEnabled = true.
AGP 9.3+ (Kotlin)
buildTypes {
release {
optimization {
enable = true // Enables code and resource optimizations.
}
}
}
AGP 9.3+ (Groovy)
buildTypes {
release {
optimization {
enable = true // Enables code and resource optimizations.
}
}
}
Устаревший DSL (Kotlin)
buildTypes {
release {
isMinifyEnabled = true
isShrinkResources = true
...
}
}
Устаревший DSL (Groovy)
buildTypes {
release {
minifyEnabled = true
shrinkResources = true
...
}
}
Если вы хотите сохранить или удалить определенные ресурсы, создайте XML-файл сохранения в ресурсах вашего проекта, например res/raw/my.package.keep.xml . Файл сохранения содержит следующие компоненты:
- Тег
<resources>— содержит все дочерние элементы ресурсов и атрибуты keep/discard. - Атрибут
tools:keep— принимает список имен ресурсов, разделенных запятыми, которые идентифицируют ресурсы для сохранения. - Атрибут
tools:discard— принимает список имен ресурсов, разделенных запятыми, которые идентифицируют ресурсы для удаления.
Используйте символ звездочки в качестве подстановочного знака для ссылки на несколько ресурсов в одной папке, например:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
tools:keep="@layout/l_used*_c,@layout/l_used_a,@layout/l_used_b*"
tools:discard="@layout/unused2" />
Указывать, какие ресурсы следует удалить, может показаться излишним, когда вместо этого можно просто их удалить, но удаление ресурсов может быть полезно при использовании вариантов сборки.
Нацелить на конкретные варианты сборки
Чтобы удалить ресурсы только в некоторых вариантах сборки, поместите все ресурсы в общий каталог проекта, а затем создайте отдельный файл my.package.build.variant.keep.xml для каждого варианта сборки в каталоге ресурсов этого варианта. В файле keep вручную укажите ресурсы, которые следует удалить, если данный ресурс, по-видимому, используется в коде (и, следовательно, не удаляется программой сжатия), но вы знаете, что на самом деле он не будет использоваться для данного варианта сборки.
Удалите неиспользуемые альтернативные ресурсы
Оптимизатор удаляет только те ресурсы, на которые не ссылается код вашего приложения, а это значит, что он не будет удалять альтернативные ресурсы для различных конфигураций устройств.
Используйте свойство resConfigs в файле build.gradle модуля вашего приложения, чтобы удалить альтернативные файлы ресурсов, которые вашему приложению не нужны.
Например, если вы используете библиотеку, содержащую языковые ресурсы (например, Google Play Services), то ваше приложение будет включать все переведенные языковые строки для сообщений из этих библиотек, независимо от того, переведено ли остальное приложение на те же языки или нет. Чтобы сохранить только те языки, которые официально поддерживает ваше приложение, укажите эти языки с помощью свойства resConfigs . Любые ресурсы для языков, не указанных в свойстве, будут удалены.
Следующие фрагменты кода показывают, как ограничить выбор языковых ресурсов только английским и французским языками:
android {
defaultConfig {
...
resourceConfigurations.addAll(listOf("en", "fr"))
}
}
или
android {
defaultConfig {
...
resConfigs "en", "fr"
}
}
При публикации приложения в формате Android App Bundle (AAB) по умолчанию загружаются только языки, настроенные на устройстве пользователя, при установке приложения. Аналогично, в загрузку включаются только ресурсы, соответствующие плотности экрана устройства, и нативные библиотеки, соответствующие ABI устройства. Для получения дополнительной информации см. раздел «Повторное включение или отключение типов конфигурационных APK-файлов» .
Для устаревших приложений, выпускаемых с APK-файлами (созданными до августа 2021 года), вы можете настроить плотность экрана или ресурсы ABI, которые будут включены в ваш APK-файл, создав несколько APK-файлов , ориентированных на различные конфигурации устройств.
Избегайте конфликтов при объединении ресурсов.
По умолчанию плагин Android Gradle (AGP) объединяет ресурсы с одинаковыми именами, например, изображения с одинаковым именем, находящиеся в разных папках ресурсов. Это поведение не контролируется свойством shrinkResources и не может быть отключено, поскольку оно необходимо для предотвращения ошибок, когда несколько ресурсов имеют имя, на которое ссылается ваш код.
Объединение ресурсов происходит только в том случае, если два или более файлов имеют идентичное имя ресурса, тип и квалификатор. AGP выбирает файл, который он считает наилучшим среди дубликатов (на основе порядка приоритетов, описанного ниже), и передает только этот ресурс в AAPT для распространения в итоговом артефакте сборки.
AGP ищет дубликаты ресурсов в следующих местах:
- Основные ресурсы, связанные с основным набором исходных файлов, обычно расположены в
src/main/res/ - Варианты наложений, зависящие от типа сборки и вариантов сборки.
- Зависимости проекта библиотеки
AGP объединяет дублирующиеся ресурсы в следующем порядке приоритета:
Например, если дублирующийся ресурс присутствует как в основных ресурсах, так и в варианте сборки, Gradle выберет ресурс в варианте сборки.
Если идентичные ресурсы находятся в одном и том же наборе исходных файлов, Gradle не сможет их объединить и выдаст ошибку слияния ресурсов. Это может произойти, если вы определили несколько наборов исходных файлов в свойстве sourceSet файла build.gradle вашего модуля, например, если и src/main/res/ и src/main/res2/ содержат идентичные ресурсы.
Устранение неполадок, связанных с нехваткой ресурсов.
При уменьшении ресурсов в окне сборки отображается сводка удаленных из приложения ресурсов. (Нажмите «Переключить отображение» в левой части окна, чтобы отобразить подробный текстовый вывод Gradle.) Например:
:android:shrinkDebugResources
Removed unused resources: Resource data reduced from 2570KB to 1711KB: Removed 33%
:android:validateDebugSigning
Gradle также создает диагностический файл с именем resources.txt в <module-name>/build/outputs/mapping/release/ (в той же папке, что и выходные файлы ProGuard). Файл содержит подробную информацию, например, о том, какие ресурсы ссылаются на другие ресурсы, а также какие ресурсы используются или удаляются.
Например, чтобы узнать, почему @drawable/ic_plus_anim_016 всё ещё присутствует в вашем приложении, откройте файл resources.txt и найдите это имя файла. Возможно, вы обнаружите, что на него ссылается другой ресурс:
16:25:48.005 [QUIET] [system.out] @drawable/add_schedule_fab_icon_anim : reachable=true
16:25:48.009 [QUIET] [system.out] @drawable/ic_plus_anim_016
Теперь вам нужно понять, почему доступен ресурс @drawable/add_schedule_fab_icon_anim ; если вы выполните поиск вверху списка, вы найдете этот ресурс в разделе «Доступные корневые ресурсы находятся в resources.txt .
Это означает, что существует ссылка на код функции add_schedule_fab_icon_anim , то есть её идентификатор R.drawable был найден в доступном коде.
Если вы не используете строгую проверку, идентификаторы ресурсов могут быть помечены как доступные, если в них присутствуют строковые константы, которые, по-видимому, используются для построения имен ресурсов для динамически загружаемых ресурсов. В этом случае, если вы выполните поиск имени ресурса в выходных данных сборки, вы можете найти сообщение примерно такого вида:
10:32:50.590 [QUIET] [system.out] Marking drawable:ic_plus_anim_016:2130837506
used because its format-string matches string pool constant ic_plus_anim_%1$d.
Если вы видите одну из этих строк и уверены, что она не используется для динамической загрузки данного ресурса, используйте атрибут tools:discard в файле keep, чтобы сообщить системе сборки о необходимости удаления ресурса.