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

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

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

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

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

В плагине Android Gradle 7.0 и более поздних версиях вы можете объявить конфигурации, которые поддерживает ваше приложение. Gradle передает эту информацию в систему сборки, используя вариант resourceConfigurations и параметр defaultConfig . Затем система сборки предотвращает появление ресурсов из других неподдерживаемых конфигураций в APK, уменьшая размер 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. Кроме того, объекты XML Drawable создают монохромные изображения, соответствующие рекомендациям 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 файлы

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

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

  • Инструмент aapt не сжимает файлы PNG, содержащиеся в папке asset/ .
  • Файлы изображений должны использовать 256 или меньше цветов, чтобы инструмент aapt мог их оптимизировать.
  • Инструмент 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 и собственного кода в вашем приложении.

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

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

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

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

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

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

Удалить символы отладки

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

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

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

Поддерживать несколько экономичных APK

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

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

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

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