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

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

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

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

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

Google Play устанавливает ограничение на размер сжатых загружаемых файлов в 200 МБ для приложений, опубликованных в составе App Bundle. Большие размеры возможны с помощью 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 удаляет неиспользуемые ресурсы.

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

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

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

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

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

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

В 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-файле.

Crunch PNG-файлы

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

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

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

        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 и нативного кода в вашем приложении можно использовать следующие методы.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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