Когда вы включаете оптимизацию приложения , параметр isShrinkResources = true
указывает оптимизатору удалить неиспользуемые ресурсы, что помогает уменьшить размер вашего приложения. Сжатие ресурсов работает только в сочетании с сокращением кода, поэтому, если вы оптимизируете ресурсы, также установите isMinifyEnabled = true
, например:
buildTypes {
release {
isMinifyEnabled = true
isShrinkResources = true
...
}
}
Если вы хотите сохранить или удалить определенные ресурсы, создайте файл сохранения XML в ресурсах вашего проекта, например res/raw/my.package.keep.xml
. Файл сохранения содержит следующие компоненты:
- Тег
<resources>
— содержит все дочерние элементы ресурсов и атрибуты сохранения/удаления. - Атрибут
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 вручную укажите ресурсы для удаления, когда данный ресурс, по-видимому, используется в коде (и, следовательно, не удаляется сжимателем), но вы знаете, что на самом деле он не будет использоваться для данного варианта сборки.
Удалить неиспользуемые альтернативные ресурсы
Оптимизатор удаляет только те ресурсы, на которые не ссылается код вашего приложения. Это означает, что оптимизатор не удалит альтернативные ресурсы для различных конфигураций устройства.
Используйте свойство Android Gradle 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) объединяет ресурсы с одинаковыми именами, например, drawables с одинаковым именем, которые находятся в разных папках ресурсов. Это поведение не контролируется свойством 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, чтобы сообщить системе сборки о необходимости удалить ресурс.