Уменьшите размер приложения

Пользователи часто избегают загрузки приложений, которые кажутся слишком большими, особенно на развивающихся рынках, где устройства подключаются к нестабильным сетям 2G и 3G или работают по тарифным планам с ограничениями по объему данных. На этой странице описывается, как уменьшить размер загрузки вашего приложения, что позволит большему количеству пользователей загрузить ваше приложение.

Загрузите свое приложение с помощью Android App Bundles

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

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

Google Play устанавливает ограничение на размер сжатой загрузки в 200 МБ для приложений, опубликованных с помощью пакетов приложений. Большие размеры возможны с использованием Play Feature Delivery и Play Asset Delivery, но увеличение размера вашего приложения может негативно повлиять на успешность установки и увеличить количество удалений, поэтому мы рекомендуем вам применить рекомендации, описанные на этой странице, чтобы максимально уменьшить размер загрузки вашего приложения.

Понять структуру APK

Прежде чем уменьшать размер приложения, полезно понять структуру APK приложения. Файл APK состоит из ZIP-архива, который содержит все файлы, составляющие ваше приложение. Эти файлы включают файлы классов Java, файлы ресурсов и файл, содержащий скомпилированные ресурсы.

APK содержит следующие каталоги:

  • META-INF/ : содержит файлы подписей CERT.SF и CERT.RSA , а также файл манифеста MANIFEST.MF .
  • assets/ : содержит активы приложения, которые приложение может извлечь с помощью объекта AssetManager .
  • res/ : содержит ресурсы, которые не скомпилированы в resources.arsc .
  • lib/ : содержит скомпилированный код, специфичный для программного слоя процессора. Этот каталог содержит подкаталог для каждого типа платформы, например armeabi , armeabi-v7a , arm64-v8a , x86 , x86_64 и mips .

APK также содержит следующие файлы. Обязательным является только AndroidManifest.xml :

  • resources.arsc : содержит скомпилированные ресурсы. Этот файл содержит XML-контент из всех конфигураций папки res/values/ . Инструмент упаковки извлекает этот XML-контент, компилирует его в двоичную форму и архивирует контент. Этот контент включает в себя языковые строки и стили, а также пути к контенту, который не включен напрямую в файл resources.arsc , например, файлы макетов и изображения.
  • classes.dex : содержит классы, скомпилированные в формате файла DEX, понимаемом виртуальной машиной Dalvik или ART.
  • AndroidManifest.xml : содержит основной файл манифеста Android. В этом файле перечислены имя, версия, права доступа и ссылочные файлы библиотеки приложения. Файл использует двоичный формат XML Android.

Уменьшить количество и размер ресурсов

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

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

Инструмент lint — статический анализатор кода, включенный в Android Studio — обнаруживает ресурсы в папке res/ , на которые не ссылается ваш код. Когда инструмент lint обнаруживает потенциально неиспользуемый ресурс в вашем проекте, он выводит сообщение, подобное следующему примеру:

res/layout/preferences.xml: Warning: The resource R.layout.preferences appears
    to be unused [UnusedResources]

Библиотеки, которые вы добавляете в свой код, могут включать неиспользуемые ресурсы. Gradle может автоматически удалять ресурсы от вашего имени, если вы включите shrinkResources в файле build.gradle.kts вашего приложения.

Котлин

android {
    // Other settings.

    buildTypes {
        getByName("release") {
            minifyEnabled = true
            shrinkResources = true
            proguardFiles(getDefaultProguardFile('proguard-android.txt'), "proguard-rules.pro")
        }
    }
}

Круто

android {
    // Other settings.

    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

Чтобы использовать shrinkResources , включите сжатие кода. В процессе сборки R8 сначала удаляет неиспользуемый код. Затем плагин Android Gradle удаляет неиспользуемые ресурсы.

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

В Android Gradle Plugin 7.0 и более поздних версиях вы можете объявить конфигурации, которые поддерживает ваше приложение. Gradle передает эту информацию в систему сборки с помощью resourceConfigurations и параметра defaultConfig . Затем система сборки предотвращает появление ресурсов из других неподдерживаемых конфигураций в APK, уменьшая размер APK. Для получения дополнительной информации об этой функции см. Удаление неиспользуемых альтернативных ресурсов .

Минимизируйте использование ресурсов библиотек

При разработке приложения Android вы обычно используете внешние библиотеки для улучшения удобства использования и универсальности вашего приложения. Например, вы можете ссылаться на AndroidX , чтобы улучшить пользовательский опыт на более ранних устройствах, или вы можете использовать Google Play Services для получения автоматических переводов текста в вашем приложении.

Если библиотека предназначена для сервера или рабочего стола, она может включать много объектов и методов, которые не нужны вашему приложению. Чтобы включить только те части библиотеки, которые нужны вашему приложению, вы можете редактировать файлы библиотеки, если лицензия позволяет вам изменять библиотеку. Вы также можете использовать альтернативную, дружественную к мобильным устройствам библиотеку, чтобы добавить определенную функциональность в ваше приложение.

Декодирование собственных анимированных изображений

В Android 12 (уровень API 31) API NDK ImageDecoder расширен для декодирования всех кадров и данных о времени из изображений, использующих анимированные форматы файлов GIF и анимированные WebP.

Используйте ImageDecoder вместо сторонних библиотек, чтобы еще больше уменьшить размер APK и воспользоваться преимуществами будущих обновлений, связанных с безопасностью и производительностью.

Более подробную информацию об API ImageDecoder можно найти в API reference и примере на GitHub .

Поддерживает только определенные плотности

Android поддерживает различные плотности экрана, например:

  • ldpi
  • mdpi
  • tvdpi
  • hdpi
  • xhdpi
  • xxhdpi
  • xxxhdpi

Хотя Android поддерживает предыдущие плотности, вам не нужно экспортировать растровые ресурсы в каждую плотность.

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

Если вашему приложению нужны только масштабированные изображения, вы можете сэкономить еще больше места, имея один вариант изображения в drawable-nodpi/ . Мы рекомендуем вам включить в ваше приложение как минимум вариант изображения xxhdpi .

Дополнительную информацию о плотности экрана см. в разделе Размеры и плотность экрана .

Используйте рисуемые объекты

Некоторые изображения не требуют статического ресурса изображения. Вместо этого фреймворк может динамически рисовать изображение во время выполнения. Drawable объекты (или <shape> в XML) могут занимать небольшое количество места в вашем APK. Кроме того, Drawable объекты XML создают монохромные изображения, соответствующие рекомендациям Material Design.

Повторное использование ресурсов

Вы можете включить отдельный ресурс для вариаций изображения, таких как тонированные, затененные или повернутые версии одного и того же изображения. Однако мы рекомендуем вам повторно использовать тот же набор ресурсов и настраивать их по мере необходимости во время выполнения.

Android предоставляет несколько утилит для изменения цвета актива, используя атрибуты android:tint и tintMode .

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

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/ic_thumb_up"
    android:pivotX="50%"
    android:pivotY="50%"
    android:fromDegrees="180" />

Рендеринг из кода

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

Файлы PNG Crunch

Инструмент aapt может оптимизировать ресурсы изображения, размещенные в res/drawable/ с помощью сжатия без потерь в процессе сборки. Например, инструмент aapt может преобразовать PNG-файл с истинным цветом, не требующий более 256 цветов, в PNG-файл с 8-битной цветовой палитрой. Это приводит к получению изображения того же качества, но с меньшим объемом памяти.

У aapt есть следующие ограничения:

  • Инструмент aapt не сжимает файлы PNG, содержащиеся в папке asset/ .
  • Для оптимизации инструментом aapt файлы изображений должны содержать не более 256 цветов.
  • Инструмент aapt может раздуть файлы PNG, которые уже сжаты. Чтобы предотвратить это, вы можете использовать флаг isCrunchPngs , чтобы отключить этот процесс для файлов PNG:
  • Котлин

        buildTypes.all { isCrunchPngs = false }
        

    Круто

        buildTypes.all { isCrunchPngs = false }
        

Сжатие файлов PNG и JPEG

Вы можете уменьшить размер файла PNG без потери качества изображения, используя такие инструменты, как pngcrush , pngquant , или zopflipng . Все эти инструменты могут уменьшить размер файла PNG, сохраняя при этом воспринимаемое качество изображения.

Инструмент pngcrush особенно эффективен. Этот инструмент перебирает фильтры PNG и параметры zlib (Deflate), используя каждую комбинацию фильтров и параметров для сжатия изображения. Затем он выбирает конфигурацию, которая дает наименьший сжатый вывод.

Для сжатия файлов JPEG можно использовать такие инструменты, как packJPG и guetzli .

Использовать формат файла WebP

Вместо файлов PNG или JPEG вы также можете использовать формат файла WebP для своих изображений. Формат WebP обеспечивает сжатие с потерями и прозрачность, как JPG и PNG, и может обеспечить лучшее сжатие, чем JPEG или PNG.

Вы можете преобразовать существующие изображения BMP, JPG, PNG или статические GIF в формат WebP с помощью Android Studio. Для получения дополнительной информации см. Создание изображений WebP .

Используйте векторную графику

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

Однако системе требуется значительно больше времени для рендеринга каждого объекта VectorDrawable , а более крупные изображения отображаются на экране еще дольше. Поэтому рассмотрите возможность использования этой векторной графики только при отображении небольших изображений.

Дополнительную информацию о работе с объектами VectorDrawable см. в разделе Drawables .

Используйте векторную графику для анимированных изображений

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

Вместо этого используйте AnimatedVectorDrawableCompat для создания анимированных векторных рисунков .

Уменьшение собственного и Java-кода

Для уменьшения размера базы кода Java и собственного кода в вашем приложении можно использовать следующие методы.

Удалить ненужный сгенерированный код

Обязательно осознайте след любого автоматически сгенерированного кода. Например, многие инструменты буферизации протоколов генерируют чрезмерное количество методов и классов, что может удвоить или утроить размер вашего приложения.

Избегайте перечислений

Один enum может добавить около 1,0–1,4 КБ к файлу classes.dex вашего приложения. Эти дополнения могут быстро накапливаться для сложных систем или общих библиотек. Если возможно, рассмотрите возможность использования аннотации @IntDef и сокращения кода для удаления перечислений и преобразования их в целые числа. Такое преобразование типов сохраняет все преимущества безопасности типов enum.

Уменьшить размер собственных двоичных файлов

Если ваше приложение использует собственный код и Android NDK, вы также можете уменьшить размер релизной версии вашего приложения, оптимизировав свой код. Два полезных метода — удаление отладочных символов и неизвлечение собственных библиотек.

Удалить отладочные символы

Использование отладочных символов имеет смысл, если ваше приложение находится в разработке и все еще требует отладки. Используйте инструмент arm-eabi-strip предоставленный в Android NDK, чтобы удалить ненужные отладочные символы из собственных библиотек. После этого вы можете скомпилировать свою сборку релиза.

Избегайте извлечения собственных библиотек

При сборке релизной версии приложения упакуйте несжатые файлы .so в APK, установив useLegacyPackaging на false в файле build.gradle.kts приложения. Отключение этого флага не позволит PackageManager копировать файлы .so из APK в файловую систему во время установки. Этот метод делает обновления вашего приложения меньше.

Поддерживайте несколько бережливых APK

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

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

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

Для получения дополнительной информации см. разделы Создание нескольких APK и Поддержка нескольких APK .