Как уменьшить размер apk android studio

Обновлено: 04.05.2024

Когда я запускаю свое приложение, размер apk будет 21 МБ. даже я включил прогард. Я использую студию Android для запуска проекта. в файлах проекта папка src имеет размер 8,62 МБ, а размер папки lib - 400 КБ. Итак, как я уменьшаю размер файла .apk. На самом деле файл .apk имеет размер 8 МБ до нескольких дней с такими же изображениями, но после интеграции с PayPal размер моего приложения увеличится до 21 МБ. размер папки сборки 127 МБ.

Я решаю эту проблему, добавляя этот код в файл приложения модуля build.gradle.

Также в случае библиотек обязательно включайте ТОЛЬКО те компоненты, которые вам действительно нужны. Также удалите ненужный и неиспользуемый импорт.

Перед тем, как нажать кнопку «Готово» при открытии мастера создания нового проекта, снимите флажок обратной совместимости (appcompat). Его можно уменьшить с 1,5 МБ до 180 КБ.

Есть несколько методов, которые можно использовать для уменьшения размера apk:

1. Proguard: в файл build.gradle для уровня приложения добавьте следующий код

2. Ненужные ресурсы: Часто ненужные ресурсы присутствуют в исходном коде. Инспектируйте исходный код с помощью Analyze-> Inspect Code. По окончании проверки удалите ненужные ресурсы.

3. Изображения Webp: изображения Webp имеют меньший размер, чем файлы PNG, а также сохраняют исходное качество изображения. Более того, изображения webp изначально поддерживаются в Android. Щелкните правой кнопкой мыши папку с возможностью рисования (/ mipmap) - & gt; Конвертировать в webp. Выберите подходящие варианты, которые соответствуют вашим потребностям.

4. Подписанный apk: размер отладочного APK больше, чем подписанный apk. Создайте подписанный apk, перейдя в Build- & gt; Создать подписанный пакет / Apk-> APK. Общий размер apk уменьшен.

5. Пакет Android App Bundle: если вы собираетесь загрузить приложение в Google Play, создайте пакет Android App Bundle вместо apk. Чтобы создать пакет приложения, перейдите на страницу Build- & gt; Создать подписанный пакет / Apk- & gt; Набор приложений для Android. Это наверняка уменьшит размер вашего приложения. Например, размер моего apk 10 МБ уменьшен до 6-7 МБ с помощью Android App Bundle.

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

Я думаю, вам следует создать свой APK как (пакет APK), Google продвигает это для проблем с размером APK. Я использовал эту опцию для своих проектов, и она действительно уменьшила размер моего APK.

shrinkResources true не будет включать изображения из ресурсов, которые вы используете в окончательной apk

Надеюсь это поможет

Эти 4 вещи уменьшают размер вашего апка почти на 50-60%

  • Заменить proguard-android.txt на proguard-android-optimize.txt
  • Сделайте minifyEnabled true
  • Добавить shrinkResources true

Подробности:

proguard-android-optimize.txt - более агрессивная конфигурация программы, чем proguard-android.txt .

Атрибут shrinkResources удалит все ресурсы, которые нигде в проекте не используются.

Атрибут resConfigs удалит все остальные локализованные ресурсы при сборке приложения. Здесь отсутствуют ресурсы на английском языке.

Оптимизация размера APK (с инструкциями по эксплуатации Android Studio)

содержание

  • С непрерывной итерацией проекта, все больше и больше функций, размер встроенного файла apk также будет становиться все больше и больше, что приведет к увеличению сетевого трафика, используемого при загрузке в мобильной сети, а apk слишком велик, Это приводит к увеличению времени загрузки. Хотя в настоящее время мобильный телефон каждого пользователя имеет большой трафик и мало влияет на трафик пользователей, согласно статистике некоторых веб-сайтов, чем больше размер установочного пакета, тем ниже коэффициент конверсии пользователя, поэтому уменьшите apk. объем может побудить большее количество пользователей загрузить и испытать продукт; [1]
  • Сжатие размера APK также имеет очень важное значение для экономии места в памяти и памяти телефона. После сжатия размера APK при запуске приложения загружается меньше ресурсов, и память телефона будет меньше занято, и в целом работа более плавная;
  • Для некоторого программного обеспечения с богатым набором функций внутри может быть принята архитектура с несколькими подключаемыми модулями, и эти подключаемые модули также могут состоять из независимых APK-файлов. Затем, когда пользователь впервые использует соответствующую функцию подключаемого модуля после загрузки программное обеспечение, это во время холодного запуска., Если APK слишком большой, это вызовет проблему медленной загрузки, что серьезно повлияет на работу пользователя.

Вот пример релизной версии APK, созданной одной из моих собственных демо-компиляций, чтобы увидеть, что установлено в APK:


Вот подробное введение в состав APK: [2]

Вот дополнение к процессу, в котором ресурсы приложения упаковываются в APK. Цепочка инструментов сборки Android использует инструмент AAPT для обработки ресурсов. Посмотрите на следующий рисунок:


3.1 Удаление ресурсов, на которые нет ссылок

В проекте Android есть более или менее несвязанные файлы ресурсов. Android Studio имеет встроенный инструмент Lint для поиска недопустимых ресурсов. Давайте возьмем Демо в качестве примера, чтобы представить конкретные шаги операции:

шаг первый:Нажмите Analyze -> Run Inspection by Name . в верхней строке меню.


Шаг второй:Поиск неиспользуемых ресурсов


Шаг третий:Настройте и начните проверку ресурсов


После запуска инструмента Lint он отобразит список файлов ресурсов, на которые нет ссылок в проекте, а затем вы можете начать удаление этих файлов:


3.2 Использование WebP для сжатия изображений

WebP - это формат файлов изображений, который обеспечивает сжатие с потерями и сжатие без потерь (обратимое сжатие). Он является производным от формата кодирования видео VP8 и считается родственным проектом мультимедийного формата WebM. WebP был впервые выпущен Google в 2010 году. Целью было уменьшить размер файла, но достичь того же качества изображения, что и формат JPEG, в надежде сократить время, необходимое для отправки файлов изображений в Интернет. [3]

Согласно предыдущему тесту Google, сжатие без потерь WebP на 45% меньше размера файла, чем файлы PNG, найденные в Интернете. Даже если эти файлы PNG обрабатываются с помощью pngcrush и PNGOUT, WebP все равно может уменьшить размер файла на 28%. [4]

Android:Android 4.0 (уровень API 14) и более поздние версии поддерживают изображения WebP с потерями, а Android 4.3 (уровень API 18) и более поздние версии поддерживают прозрачные изображения WebP без потерь.

IOS:Текущая iOS не поддерживает webp, и я не знаю, будет ли она поддерживать его в будущем, поэтому после получения изображения в формате webp из Интернета его нельзя отобразить напрямую. Данные данных необходимо преобразовать в jpg или png для отображения.

Давайте поговорим о встроенном инструменте конвертации webp и этапах работы Android Studio:

шаг первый:Щелкните правой кнопкой мыши изображение, которое вы хотите преобразовать, и выберите преобразовать в webp .


Шаг второй:Настроить и начать конвертацию


3.3 Используйте TinyPNG для сжатия изображений

TinyPNG - это бесплатный онлайн-инструмент для сжатия изображений без потерь, эффект сжатия хороший, рекомендую всем:


4.1 Обфускация кода

Обфускация кода заключается не в том, чтобы код не мог быть декомпилирован, а в том, чтобы переименовать классы, методы, переменные и другую информацию в коде, чтобы изменить их на какие-то бессмысленные имена. В то же время он также может удалить неиспользуемые классы, методы , переменные и т. д. Таким образом, интуитивно обфускация может повысить безопасность программы, повысить сложность обратного проектирования и эффективно уменьшить размер apk. Основные функции следующие: [5]

  • Переименуйте классы, методы, переменные и другую информацию в проекте в бессмысленные короткие имена;
  • Удалите неиспользуемые классы, методы, переменные и т.д .;

Сделайте следующую конфигурацию в файле gradle в главном модуле приложения: [1]

Используйте shrinkResources для удаления, но чтобы использовать shrinkResources, вы должны сначала включить обфускацию кода minifyEnabled.

В дополнение к свойству minifyEnabled существует также свойство proguardFiles, используемое для определения правил ProGuard:

  • getDefaultProguardFile(‘proguard-android.txt') Из Android SDK tools/proguard/ Папка получает настройки ProGuard по умолчанию.
  • proguard-rules.pro Файл используется для добавления пользовательских правил ProGuard. По умолчанию этот файл находится в корневом каталоге модуля (рядом с файлом build.gradle).

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

4.2 Используйте Lint, чтобы найти бесполезный код

Как и в предыдущем случае, используя Lint для поиска ресурсов, на которые нет ссылок, нажмите Analyze -> Analyze -> Run Inspection by Name . в строке меню.

Найдите неиспользованное объявление следующим образом:



В результатах поиска будут перечислены классы / методы / переменные, на которые не было ссылок, а затем вы можете рассмотреть возможность удаления этих бесполезных кодов:


Через aapt l -v xxx.apk или unzip -l xxx.apk вы можете просмотреть детали APK:



Из рисунка выше видно, что многие ресурсы в APK Stored Для хранения эти файлы не сжимаются. Найдите следующее описание в исходном коде AAPT:

Видно, что AAPT не сжимает эти ресурсы файловых суффиксов во время обработки ресурсов.Можно ли изменить их метод сжатия для достижения эффекта похудания? Подробный метод сжатия может относиться к:Техническая команда Meituan - практика оптимизации похудения пакета приложений для Android

Как оптимизировать размер classes.dex обычно есть два направления: [2]

  • Всегда придерживайтесь хороших навыков программирования и четко понимайте размер пакета, удаляйте повторяющийся или неиспользуемый код, с осторожностью используйте сторонние библиотеки, выбирайте небольшие сторонние SDK и т. Д .;
  • Включите ProGuard для сжатия кода и используйте ProGuard для обфускации, оптимизации и сжатия кода.

При разработке приложений для Android вы часто используете внешние библиотеки, чтобы улучшить удобство использования и масштабируемость вашего приложения. Например, вы представите библиотеку поддержки Android, чтобы улучшить взаимодействие с пользователем на старых моделях, или вы будете использовать службу Google Play для автоматического перевода текста в своем приложении. Если библиотека разработана как служба или рабочий стол, она будет содержать множество объектов и методов, которые ваше приложение не использует. Чтобы включить только те части, которые используются в вашем проекте, вы можете изменить этот файл библиотеки.Если лицензия позволяет, вы также можете использовать другую мобильную библиотеку для добавления определенных функций в свое приложение. [6]

нота:Progard может удалить какой-то бесполезный код в импортированной библиотеке, но не может удалить большие внутренние зависимости в библиотеке.

Введение в upx (степень сжатия 50%

[1] Узнайте, как оптимизировать объем APK для Android почти столбцов

[2] Техническая команда Meituan - практика оптимизации похудения пакета приложений для Android

[4] Формат Baidu Encyclopedia-webp

[5] Подробное объяснение обфускации кода Nuggets-Android

[6] Jianshu-Performance Optimization (6) -Уменьшение размера APK

Интеллектуальная рекомендация

Замена персонажа

Пожалуйста, реализуйте функцию для преобразованияЗаменить каждый пробел"% 20". Например, когда строка We We Happy. Строка после замены - We% 20Are% 20Happy. Встроенные функции для строк Pyth.


Подсистема ввода Android - Itreader EventHub :: GetEvents Mneedtscandevices Переменные Подробный анализ

EventHub :: MeetEvents Method, Mneedtscandevices Переменная процесса вызова подробный анализ . if (mNeedToScanDevices.


Базовые знания Python3: List

Просто поймите: 1. Типы элементов в списке могут быть разными, он поддерживает числа, строки и даже списки (так называемая вложенность). 2. Список представляет собой список элементов, заключенн.


NOIP 2017 Улучшенное сокровище группы ___ государственное давление dp + dfs

Главная идея: ответ: Этот вопрос найти несложно, f [i] указывает, что состояние выбранной точки равно i, это минимальная стоимость, а dis [i] указывает количество сокровищ от начальной точки до i. , а.

HYSBZ-2002: Bounce Bouncing Sheep (алгоритм блокировки)

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

Применим этот принцип в Android. Мы собираемся поиграть в APK-гольф и создать приложение минимально возможного размера, которое можно установить на Android 8.0 Oreo.

Базовый уровень

Начнём с дефолтного приложения, который генерирует Android Studio. Создадим хранилище ключей, подпишем приложение и измерим размер файла в байтах командой stat -f%z $filename .

Затем установим APK на смартфон Nexus 5x под Oreo, чтобы убедиться, что всё работает.


Прекрасно. Наш APK весит примерно полтора мегабайта.

APK Analyser

Полтора мегабайта кажутся слишком большим размером с учётом того, что делает наше приложение (а оно ничего не делает), так что давайте изучим проект и поищем, где по-быстрому сэкономить на объёме. Вот что сгенерировал Android Studio:

  • MainActivity , который расширяет AppCompatActivity .
  • Файл макета с ConstraintLayout для главного окна.
  • Файлы ресурсов с тремя цветами, одним строковым ресурсом и темой.
  • Библиотеки поддержки AppCompat и ConstraintLayout .
  • Один AndroidManifest.xml .
  • Файлы PNG для квадратной, круглой и фоновой иконок.


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

Файл Размер
classes.dex 74%
res 20%
resources.arsc 4%
META-INF 2%
AndroidManifest.xml <1%

Исследуем по отдельности, что делает каждый файл.

Файл Dex

classes.dex — главный виновник раздутого APK, он занимает 73% всего объёма и поэтому станет первой целью оптимизации. Этот файл содержит весь наш скомпилированный код в формате Dex, а также список внешних методов во фреймворке Android и библиотеку поддержки.

В пакете android.support перечисляется более 13 000 методов, что кажется излишним для приложения типа "Hello World".

Ресурсы

В директории res находится большое количество файлов шаблонов, чертежей (drawables) и анимаций, которые сразу не видны в интерфейсе Android Studio. Опять же, они вытянуты из библиотеки поддержки и занимают около 20% размера APK.


Файл resources.arsc также содержит список всех этих ресурсов.

Подпись

В папке META-INF находятся файлы CERT.SF , MANIFEST.MF и CERT.RSA , которые нужны для подписи v1 APK. Если злоумышленник изменит код внутри APK, то подписи не совпадут, что защищает пользователя от запуска постороннего зловреда.

В MANIFEST.MF перечисляются файлы из APK, а CERT.SF содержит контрольные суммы манифеста и каждого отдельного файла. В CERT.RSA хранится открытый ключ, которым проверяется цельность CERT.SF .


Здесь нет очевидных целей для оптимизации.

AndroidManifest

AndroidManifest очень похож на наш оригинальный файл. Единственное отличие — вместо ресурсов вроде строк и drawables здесь указаны их целочисленные идентификаторы, начиная с 0x7F .

Включаем минификацию

Мы ещё не пробовали включить опцию минификации и сжатия ресурсов в файле build.gradle для нашего приложения. Сделаем это.

Если установить minifyEnabled в значение true , то активируется Proguard, который очищает приложение от ненужного кода. А также обфусцирует имена символов, затрудняя обратную разработку приложения.

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

786 КБ (уменьшение на 50%)

Мы наполовину уменьшили размер APK без видимого изменения в работе программы.


Если вы ещё не включили minifyEnabled и shrinkResources в своём приложении, это самая главная вещь, которую следует вынести из этой статьи. Можно легко сэкономить несколько мегабайт, потратив всего парочку часов на конфигурацию и тестирование.

Прощай, AppCompat, мы едва тебя узнали

classes.dex теперь занимает 57% всего APK. Основная часть списка методов из файла Dex принадлежит пакету android.support , так что мы собираемся удалить библиотеку поддержки. Для этого нужно сделать следующее:

    Полностью удалить блок зависимостей из build.gradle .

108 КБ (уменьшение на 87%)

Матерь божья, файл уменьшился почти в десять раз: с 786 КБ до 108 КБ. Единственным заметным изменением стало только изменение цвета тулбара, который окрасился в дефолтную тему ОС.


На директорию res теперь приходится 95% размера APK из-за всех этих иконок лаунчера. Если бы эти иконки делал наш дизайнер, мы бы попытались конвертировать их в WebP, более эффективный формат, который поддерживается в API 15 и более поздних версиях.

К счастью, Google уже оптимизировала наши drawables, хотя в противном случае мы бы и сами могли оптимизировать их и удалить из PNG ненужные метаданные с помощью ImageOptim.

Давайте поступим нешаблонно — и заменим все наши иконки запуска единственной однопиксельной чёрной точкой в папке res/drawable . Эта картинка весит 67 байт.

6808 байт (уменьшение на 94%)

Мы избавились почти от всех ресурсов, так что неудивительно, что размер APK уменьшился примерно на 95%. В файле resources.arsc по-прежнему упоминаются следующие ресурсы:

  • 1 файл шаблона
  • 1 строковый ресурс
  • 1 иконка лаунчера

Файл шаблона (6262 байта, сокращение на 9%)

Фреймворк Android раздувает наш файл XML и автоматически создаёт объект TextView , который используется как contentView для Activity .

Попробуем обойтись без этого посредника, удалив файл XML и программно задав contentView. Объём ресурсов уменьшится, потому что исчезнет файл XML, но увеличится размер файла Dex, поскольку мы упоминаем там дополнительные методы TextView .


Выглядит как неплохой обмен.

Имя приложения (6034 байта, сокращение на 4%)

Давайте удалим strings.xml и заменим android:label в манифесте AndroidManifest буквой "A". Это кажется маленьким изменением, но удаление записи из resources.arsc уменьшает количество символов в манифесте и удаляет файл из директории res. Каждая мелочь идёт на пользу — мы только что сэкономили 228 байт.

Иконка лаунчера (5300 байт, сокращение на 13%)

Документация для resources.arsc в репозитории Android Platform объясняет, что каждый ресурс APK упоминается в resources.arsc с целочисленным идентификатором. У этих ID два пространства имён:

0x01: системные ресурсы (предустановленные в framework-res.apk)

0x7f: ресурсы приложения (в файле .apk приложения)

Так что произойдёт с нашим APK, если мы поставил ссылку на ресурс в пространстве имён 0x01? По идее, мы получим более красивую иконку и одновременно уменьшим размер своего файла.



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

Манифест (5252 байта, сокращение на 1%)

Мы ещё не трогали манифест.


Удаление этих аттрибутов экономит 48 байт.

Хак Proguard (4984 байта, сокращение на 5%)

Похоже, что классы BuildConfig и R ещё остались в файле Dex.


Уточнение правила Proguard удалит ненужные классы.

Обфускация (4936 байт, сокращение на 1%)

Обфусцируем имя для класса Activity. Для обычных классов Proguard автоматически делает это, но поскольку имя класса Activity вызывается через Intents, его не обфусцировали по умолчанию.

META-INF (3307 байт, сокращение на 33%)

В данный момент мы подписываем приложение одновременно подписями v1 и v2. Это кажется лишней тратой ресурсов, потому что v2 обеспечивает превосходную защиту и производительность, хешируя весь APK целиком.

Подпись v2 не видна из APK Analyser, поскольку включена в бинарный блок в самом файле APK. Подпись v1 видна, в виде файлов CERT.RSA и CERT.SF .

Давайте уберём галочку для подписи v1 в интерфейсе Android Studio и сгенерируем подписанный APK. Попробуем сделать и наоборот.

Подпись Размер
v1 3511
v2 3307

Похоже, теперь мы будем использовать v2.

Пришло время редактировать APK вручную. Используем следующие команды:


Детальный обзор процесса подписи APK см. здесь. В общем, Gradle генерирует неподписанный архив, zipalign делает выравнивание по границе байта для несжатых ресурсов, чтобы оптимизировать потребление RAM после загрузки APK, и в конце запускается криптографическая процедура подписи APK.

Неподписанный и невыровненный APK весит 1902 байт, то есть процедура добавляет примерно 1 килобайт.

Несоответствие размеров файлов (2608 байт, сжатие на 21%)

Странно! Если разархивировать невыровненный APK и подписать его вручную, то пропадает файл META-INF/MANIFEST.MF , что экономит 543 байта. Если кто-то знает, почему так происходит, то дайте знать!

Теперь у нас в подписанном APK осталось три файла. Но ведь мы можем ещё избавиться от файла resources.arsc , потому что не устанавливаем никаких ресурсов!

После этого остаётся только манифест и файл classes.dex , оба примерно одинакового размера.

Хаки со сжатием (2599 байт, сокращение на 0,5%)

Теперь изменим все оставшиеся строки на ‘c’, обновив версии до 26, а затем сгенерируем подписанный APK.

Это уменьшает размер ещё на 9 байт.

Хотя количество символов в файле не изменилось, но дело в том, что увеличилась частотность символа ‘c’. В результате алгоритм сжатия сработал более эффективно.

Привет, ADB (2462 байт, сокращение на 5%)

Можно ещё сильнее оптимизировать манифест, удалив фильтр намерения Launch для класса Activity. С этого момента будем запускать приложение следующей командой:

adb shell am start -a android.intent.action.MAIN -n c.c/.c

Вот новый манифест:


Мы также избавились от иконки лаунчера.

Очистка от ссылок на методы (2179 байт, сокращение на 12%)

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

Наше приложение перечисляет методы в классах TextView , Bundle и Activity . Можно уменьшить размер файла Dex, удалив эти ссылки и заменив их новым классом Application . Таким образом, файл Dex теперь будет ссылаться на единственный метод — конструктор класса Application .

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

Используем adb для проверки, что APK успешно установился, это можно также проверить через «Настройки».


Оптимизация Dex (1961 байт, сокращение на 10%)

Я потратил несколько часов, изучая формат файла Dex ради этой оптимизации, поскольку разные механизмы вроде контрольных сумм и смещений затрудняют ручное редактирование.

Если вкратце, в итоге выяснилось, что единственным требованием для установки APK является факт существования файла classes.dex . Поэтому мы просто удалим оригинальный файл, запустим touch classes.dex в консоли и сэкономим 10% от размера, используя пустой файл.

Иногда глупейшее решение — самое лучшее.

Понимание манифеста (1961 байт, сокращение на 0%)

Манифест неподписанного APK — это файл в бинарном формате XML, который вроде бы официально не документирован. Можно изменить содержимое файла с помощью редактора HexFiend.

В заголовке файла угадываются некоторые интересные элементы — первые четыре байта кодируют 38 , что совпадает с номером версии файла Dex. Следующие два байта кодируют 660 , что совпадает с размером файла.

Попробуем удалить один байт, установив targetSdkVersion на 1 , и изменив размер файла в заголовке на 659 . К сожалению, система Android отвергает новый файл как неправильный APK. Похоже, тут всё устроено как-то посложнее…

Непонимание манифеста (1777 байт, сокращение на 9%)

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

Удивительно, но такой манифест воспринят как валидный APK на Nexus 5X под Oreo:


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

Для максимальной выгоды нужно заменить все эти глупые символы нулевыми байтами. Это поможет распознать важные части файла в HexFiend, а также сократит несколько байт благодаря хаку сжатия, упомянутому выше.

Манифест UTF-8

Вот важные компоненты Manifest, без которых APK не установится.


Некоторые вещи очевидны, такие как теги манифеста и пакета. В пуле строк видны versionCode и название пакета.

Шестнадцатиричный манифест


Просмотр файла в шестнадцатиричном виде показывает значения в заголовке файла, которые описывают пул строк и другие значения, вроде размера файла 0x9402 . Строки тоже интересно закодированы — если они больше 8 байт, то общая длина указывается в двух предыдущих байтах.

Но вряд ли здесь можно найти другие варианты для оптимизации.

Готово? (1757 байт, сокращение 1%)

Изучим окончательный APK.


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


Мы сэкономили 20 байт.

Шаг 5: Признание

1757 байт — это очень мало, чёрт возьми. И насколько я знаю, это самый маленький существующий APK.

Однако я разумно полагаю, что кто-нибудь из Android-сообщества способен выполнить дальнейшие оптимизации и ещё улучшить результат. Если вы умудритесь уменьшить файл с нынешних 1757 байт, присылайте пулл-реквест в репозиторий, где хостится самый маленький APK, или сообщайте в твиттере. (С момента публикации статьи файл уже уменьшили до 820 байт — прим. пер.)

Рекомендую сначала прочитать статью Playing APK Golf (или её перевод). Это крайне интересно, как исследовательская работа, но абсолютно неприменимо в реальной разработке.

Proguard

При сборке apk в его dex файл (или файлы) попадает весь код приложения и весь код всех подключенных библиотек, даже неиспользуемый. Хорошо бы от этого лишнего кода избавиться. Для этих целей есть специальный инструмент под названием proguard. Он уже включён в Android SDK и любой Android проект из коробки настроен для работы с ним. Данный инструмент делает следующее:

  • Удаляет неиспользуемые классы, методы и поля;
  • Оптимизирует Java байткод;
  • Слегка обфусцирует код переименованием классов, методов и полей.

Всё это происходит на уровне Java байткода (не dex байткода), то есть файлов .class. На вход подаются jar(aar) файлы, а на выходе получаются они же, но в оптимизированном виде. В результате вес байткода значительно уменьшается.


В простейшем случае для включения proguard нужно открыть build.gradle конфиг уровня приложения и в блоке android/buildType/release выставить свойству minifyEnabled значение true:

Если в проекте есть классы, которые участвуют в рефлексии, нужно запретить их переименование, так как при попытке обращения к классам(и их свойствам и методам), которые были переименованы, приложение упадёт с исключением. Это также касается pojo(data) классов, которые маппятся, например, через Gson, Firebase Database или какой-нибудь ORM. Для того, чтобы оставить такие классы без изменений, нужно в файле proguard-rules.pro применить к ним правило -keep:

Или для всего пакета:

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


Размер приложения уменьшился с семи мегабайт до трёх с половиной и это только за счёт оптимизации байткода. Посмотрим, что внутри через APK Analyzer:



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

Также стоит упомянуть о существовании инструмента под названием DexGuard, который оптимизирует dex байткод, но он платный и простым смертным недоступен.

shrinkResources

Теперь при сборке apk можно увидеть следующую строку:


В итоге apk уменьшился на 32 килобайта:


Не очень много, но тоже хорошо. Тут всё зависит от проекта, иногда вырезается более ощутимый объём.

Данная опция не будет работать, если в приложении есть модули Dynamic Features и\или Instant App.

Удаление ненужных языковых ресурсов

Некоторые библиотеки, особенно гугловские support lib(androidx) и firebase, содержат ресурсы для множества языков. Чтобы их удалить нужно явно указать, какие языки используются в приложении. Это делается в build.gradle уровня приложения в блоке android/defaultConfig (или в конкретном конфиге):

В моём случае это русский и английский. При сборке в apk будут включены только ресурсы для указанных языков. Посмотрим, что получилось:


Вес apk уменьшился ещё на 265 килобайт. Неплохо. Посмотрим, что внутри:


В apk остались языковые ресурсы только для русского и английского. Было 86 языков, а осталось только два.

Ещё одно средство для оптимизации байткода, но уже от гугла. Думаю, есть ненулевая вероятность того, что R8 когда-нибудь полностью заменит proguard. Этот инструмент встроен прямо в компилятор D8, который превращает Java байтод в dex байткод. В отличии от proguard, R8 работает в момент компиляции java байткода в dex байткод, что немного уменьшает общее время сборки apk.



R8 можно включить в Android Studio, начиная с версии 3.3, а с версии 3.4 он включен по-умолчанию. Для включения R8 нужно открыть файл gradle.properties и добавить строку:

Кроме этого, можно включить агрессивный режим оптимизации строкой:

Но эта функция, пока что, нестабильна и не рекомендуется к использованию.

R8 поддерживает правила для proguard (упоминавшийся ранее файл proguard-rules.pro) и точно так же генерирует файлы mapping.txt, seeds.txt и usage.txt. Кроме вырезания ненужного кода и обфускации, R8 также оптимизирует dex байткод (помним, что proguard оптимизирует только java байткод). После сборки видим, что удалось сэкономить ещё 28 килобайт за счёт уменьшения dex файла:


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

App Bundle

После сборки получается файл:


Его вес больше, чем вес apk, но это не имеет значения. По сути, это сырой файл приложения из которого могут быть сгенерированы apk файлы, которые можно устанавливать на android устройства. Этот файл загружается в Google Play Console, вместо apk, и там происходит магия. Приложение разбивается на основной apk и на набор apk конфигурации. При установке на устройство приложение собирается по частям:

При загрузке бандла в Google Play Store можно увидеть, сколько будет весить приложение:


На IO 2018 показывали такую картинку:


Для проверки и тестирования есть утилита bundletool. Она позволяет генерировать apk из бандла и манипулировать ими.

Dynamic Features

Удаление метаданных kotlin из сборки

Ещё один простой способ, подсмотренный в этой статье. В META-INF записываются дополнительные данные для рефлексии. Если в приложении не используется полноценная kotlin рефлексия(пакет kotlin-reflect), то эти файлы можно не включать в приложение. Для этого в gradle конфиге уровня приложения в блоке android нужно прописать следующее:

В моём случае вес приложения уменьшился ещё на 412 килобайт. Здесь показатель уменьшения веса напрямую зависит от количества кода в приложении. После сборки приложения стоит убедиться, что ничего не поломалось, так как рефлексия может использоваться в подключенных библиотеках. Также можно исключать отдельные файлы, чтобы оставить нужные для рефлексии.

И это ещё не всё

apk формат Android приложений

Всем известно, что Android Market накладывает ограничение на размер публикуемых программ. Сегодня в магазине можно разместить приложение, размер которого не превосходит 50 Мб, но что же делать, если Вы вылезли за это ограничение?Дэвид Карлссон, архитектор приложений из Sony Ericsson, дает несколько советов, которые помогут уменьшить размер вашего apk файла.

Что такое APK формат?

APK- аббревиатура от Android application package (файл архива Android программы). Каждое Android приложение упаковывается в apk архив, содержащий исполняемый код (.dex файлы), ресурсы, активы и файл манифеста. Фактически apk представляет собой обычный zip архив, поэтому не имеет смысла предварительно сжимать файлы ресурсов каким-нибудь архиватором.

Дэвид Карлссон, SE

Ниже приводится несколько полезных советов, которые помогут вам уменьшить размер ваших Android программ.

Используйте ProGuard

ProGuard- это обфускатор, попутно сжимающий размер кода. Как известно, Java приложения компилируются в байт-код, из которого довольно просто восстановить java исходник. Для усложнения жизни любителям реверс-инженерии придумали обфускаторы. Обфускатор служит для запутывания исходного кода программы, при сохранении исходной функциональности. Получается рабочий исходник, мало пригодный для чтения человеком. Программа ProGuard помимо собственно обфускации сжимает исходный код, делает его более быстрым и менее требовательным к памяти. Очень важно после использования ProGuard провести тщательное тестирование полученного приложения. Возможны ситуации, когда в ходе оптимизации и обфускации кода изменяется его функциональность. В таких случаях важно позаботиться о сохранении symbol mapping, чтобы можно было восстановить из обфусцированного кода исходный и попытаться выявить источник проблем.

Удаляйте отладочную информацию

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

Часто начинающие разработчики оформляют отладочный код в виде отдельных методов

Это не лучшее решение, поскольку на этапе сборки релиза будет удален блок if (Debug) , но сам методmyDebugPrint() и его вызов останутся нетронутыми и будут занимать место.

Удаляйте отладочные символы из нативных библиотек

Использование символов отладки имеет смысл, когда ваше приложение находится в стадии разработки. Если Вы решили собрать релиз, Дэвид рекомендует удалить символы отладки из нативных библиотек (.so файлы). Это можно сделать, вызвав команду arm-eabi-strip из Android NDK.

Используйте рекомендуемые медиа форматы

Если ваше приложение содержит графику, видео и аудио данные, использование "правильных" форматов может положительно сказаться на размере приложения. Дэвид рекомендует использовать следующие форматы:

  • Рисунки: PNG и JPEG. Формат PNG позволяет добиваться хорошей компрессии при отсутствии ухудшения качества картинки. JPEG хорош для больших по разрешению картинок.
  • Аудио: Используйте ACC Audio. Этот формат обеспечивает лучшую компрессию, чем широко распространенные mp3 и Ogg Vorbis. Никогда не используйте wav. Это формат для профессиональных музыкантов. В нем не используется компрессия и содержится много избыточной информации. Часто wav используется для декодирования сжатого аудио потока. Обычно такой подход сопровождается заметными временными задержками. Android имеет средства для воспроизведения сжатого аудио потока лишенные этого недостатка (Sound Pool API).
  • Видео: Используйте формат H264 AVC. Если видеофайл имеет большое разрешение, обязательно перекодируйте его под разрешение экрана целевого устройства.

Компрессируйте PNG файлы

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

Используйте 9patch PNG для масштабируемых изображений

9patch PNG- специальный формат, который может быть использован для создания растягиваемых подложек. Наиболее часто этот формат используется для создания кнопок и других элементов пользовательского интерфейса. В рамках 9patch картинка разбивается на 9 сегментов - четыре угла, четыре грани и центральная часть. На основе такой картинки можно создавать подложки произвольного размера, при этом угловые сегменты никак не масштабируются; ребра и центральный сегмент растягиваются (многократно повторяются), заполняя промежутки между углами. Ниже показана 9patch картинка и две сгенерированные на ее основе кнопки. Применение этого формата позволяет существенно уменьшить размер графики, необходимой для создания интерфейса.

9patch PNG

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

Как правило, папка res содержит несколько неиспользуемых ресурсов. Для их удаления можно использовать специальную утилитуandroid-unused-resources, которая сканирует Ваш исходный код и удаляет из проекта неиспользуемые ресурсы.

Избегайте дублирования

Убедитесь, что в вашем приложении не дублируется функциональность и активы (строки, рисунки и т.п.). Важно понимать, какие Android API вы используете, и знать их функциональность. Может получиться, что в вашей программе для решения задачи, которую можно решить средствами уже подключенных API, подключается новый API. Дублирование кода, например, включение в программу функций делающих одно и то же, также ведет к разбуханию APK файлов.

Читайте также: