Build


https://developer.android.com/build
https://developer.android.com/build/annotation-processors
https://developer.android.com/build/jdks
https://developer.android.com/build/configure-app-module
https://developer.android.com/build/manage-manifests
https://developer.android.com/build/custom-build-logic
https://developer.android.com/build/build-variants
https://developer.android.com/build/agp-upgrade-assistant
https://developer.android.com/build/sdk-upgrade-assistant
https://developer.android.com/build/sdk-upgrade-assistant
https://developer.android.com/build/build-analyzer
https://developer.android.com/build/profile-your-build
https://d.android.com/studio/build/shrink-code
https://developer.android.com/build/kotlin-support
https://developer.android.com/build/multidex
https://developer.android.com/tools/adb
https://developer.android.com/build/dependencies
https://developer.android.com/build/native-dependencies
https://developer.android.com/build/remote-repositories
https://developer.android.com/studio/write/lint
03.04.2024https://habr.com/ru/companies/cian/articles/804835/
01.10.2020https://habr.com/ru/articles/521522/
https://docs.gradle.org/current/userguide/compatibility.html
https://docs.gradle.org/current/userguide/build_environment.html

R8

Используется вместо Proguard начиная с версии AGP 3.4.

NDK

Native Development Kit – набор инструментов, которые помогают работать с кодом, написанным на языках C и C++. NDK предоставляет API для доступа к физическим компонентам девайса, таким как сенсоры. Кроме того NDK позволяет скомпилировать и включить в APK C/C++ код, используя Gradle. NDK часто используется в геймдеве для увеличения производительности и для ручного управления памятью. Для взаимодействия нативного и Java-кода используется собственный интерфейс Java - JNI, он определяет способ взаимодействия байт-кода, который Android компилирует из управляемого кода (написанного на языках программирования Java или Kotlin), с собственным кодом (написанным на C/C++).

JNI

Java Native Interface. Стандартный механизм для запуска кода под управлением JVM, который написан на языках C/C++ или Ассемблере и скомпонован в виде динамических библиотек; позволяет не использовать статическое связывание. Это даёт возможность вызова функции C/C++ из программы на Java, и наоборот.

Android

ОС для смартфонов, планшетов, носимой электроники и бытовых устройств с открытым исходным кодом. Основана на ядре Linux. Android использует собственную реализацию виртуальной машины Java - ART. Позволяет запускать Java-приложения, управляющие устройством через разработанные Google библиотеки.

ART

Android Runtime (ART) - среда выполнения приложений Android, замена Dalvik, преобразовывает байт-код приложений в собственные инструкции, которые выполняются на устройстве.

jar

Java Archive. Содержит классы Java, может использоваться как в Android-приложениях, так и в чистой Java.

aar

Android Archive. Аналогичен модулю приложения Android. Может включать исходный код (классы и методы Java), файлы ресурсов, манифест. Может содержать библиотеки C/C++.

Debugger

• устанавливать точки останова (поэтапное выполнение программ)

• проверять значения переменных

Запустить отладку

• Run → Attach Debugger to Android Process (или иконка жука со стрелкой)

• Нажать иконку жука

• Открыть окно Debug

Breakpoints

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

Incremental build

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

Modularization

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

Gradle

Система автоматической сборки проектов.

miSdk

Минимальная версия Android, на которой ваше приложение может работать. Определяет, какие API и функции из SDK доступны при компиляции. Это не влияет на то, на каких версиях Android ваше приложение будет работать, а лишь на то, какие функции и классы вы можете использовать в коде.

compileSdk

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

targetSdk

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

Подключение модулей и зависимостей

КонфигурацияПоведение
implementationПолучить доступ к модулю или библиотеке без внутренних зависимостей. Использование улучшает время сборки.
apiЗамена устаревшего compile. Получить доступ к модулю или библиотеке. А также к модулям и библиотекам подключенным внутри. Позволяет транзитивно использовать внутренние зависимости в compiletime и runtime.
compileOnlyЗависимость доступна только в compiletime. Например библиотека только с аннотациями для генерации кода. Нельзя использовать с AAR.
runtimeOnlyЗависимость доступна только в runtime. Редко используется. Пример - логирование в серверных приложениях.
kaptЗамена устаревшего annotationProcessor. Обработчики аннотаций поддерживаются с помощью плагина кампилятора kapt (замена annotationProcessor). Kapt использует компилятор Java для запуска обработчиков аннотаций.
kspKotlin Symbol Processing - используется для легковесных подключаемых модулей. Работает до 2 раз быстрее kapt. Не привязан к JVM. Минимизирует время сборки.

Build Variants & Product Flavors

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

buildTypes {
    release {
        isMinifyEnabled = true
        isShrinkResources = true
        signingConfig = signingConfigs.getByName("release")
        applicationIdSuffix = MoviesBuildType.RELEASE.applicationIdSuffix
        manifestPlaceholders += mapOf("appName" to "@string/app_name")
        proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
    }
    debug {
        isDebuggable = true
        isMinifyEnabled = false
        isShrinkResources = false
        applicationIdSuffix = MoviesBuildType.DEBUG.applicationIdSuffix
        manifestPlaceholders += mapOf("appName" to "@string/app_name_dev")
        isDefault = true
    }
}
flavorDimensions += "version"

productFlavors {
    create("gms") {
        dimension = "version"
        applicationId = "org.michaelbel.moviemade"
        isDefault = true
    }
    create("hms") {
        dimension = "version"
        applicationId = "org.michaelbel.movies"
    }
    create("foss") {
        dimension = "version"
        applicationId = "org.michaelbel.movies"
    }
}
ProGuard

Инструмент оптимизации и обфускации (запутывание) Java кода. Proguard удаляет неиспользуемые классы и методы из уже скомпилированного приложения. Это позволяло решать проблему 64К методов до появления MultiDex. Java- и Dalvik-байткод легко декомпилировать. Для серверного Java-приложения это не проблема, а вот к байткоду приложения под Android доступ имеет любой пользователь. Proguard обфусцирует код, что усложняет задачу декомпиляции. Этот инструмент обрабатывает уже скомпилированный Java код, так что он должен работать с любым JVM языком. Сам язык для Proguard безразличен, важен только байткод. Все манипуляции Proguard с байткодом можно разделить на 3 основных категории: Code shrinking, Optimisation и Obfuscation.

Работает в Release - не работает в Debug ?

Проблема в Proguard

@Keep

Гарантирует, что аннотированный класс или метод не будет удален при минимизации кода во время сборки. Обычно добавляется к методам и классам, доступ к которым осуществляется через рефлексию, чтобы компилятор не рассматривал код как неиспользуемый. Классы и методы @Keep всегда появляются в APK-файле, даже если вы никогда не ссылаетесь на эти классы и методы в логике приложения.

APK (Android Package)

Формат пакета для приложений на платформе Android. Он содержит все необходимые файлы и ресурсы, которые требуются для установки и запуска приложения на устройстве Android. APK-файл представляет собой архив, который можно рассматривать как “упакованный” контейнер для всего, что нужно для работы приложения.

Компоненты APK-файла

META-INF Содержит метаданные о приложении, включая цифровые подписи и сертификаты, которые используются для проверки целостности и подлинности APK.

MANIFEST.MF Файл манифеста, который содержит общую информацию о содержимом архива, например, метаданные подписи.

CERT.RSA Цифровая подпись для проверки целостности файла.

CERT.SF Файл, который содержит список файлов в APK и их хэши для проверки целостности.

res Содержит ресурсы приложения, такие как файлы разметки (XML), изображения и другие ресурсы, которые не являются кодом. Эти файлы упакованы в формат, оптимизированный для быстрого доступа.

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

lib Содержит скомпилированные библиотеки и файлы .so (shared objects) для различных архитектур процессора (например, ARM, x86). Эти библиотеки могут использоваться приложением для выполнения задач на низком уровне или взаимодействия с платформенными функциями.

classes.dex Содержит скомпилированные байт-коды Java (в формате Dalvik Executable) или Kotlin, которые выполняются виртуальной машиной Android (ART/Dalvik). Это основной исполняемый код приложения.

AndroidManifest.xml Основной файл конфигурации, который описывает компоненты приложения (активности, службы, приемники, провайдеры контента) и задает разрешения, необходимые приложению. Этот файл также содержит информацию о версии приложения и других свойствах.

resources.arsc Содержит предварительно скомпилированные ресурсы (например, строки, стили, размеры) в бинарном формате, который позволяет быстро извлекать их во время выполнения приложения.

Структура APK-файла

MyApp.apk
├── AndroidManifest.xml
├── classes.dex
├── res/
│   ├── drawable/
│   ├── layout/
│   ├── mipmap/
│   └── values/
├── assets/
│   └── some_file.txt
├── lib/
│   ├── armeabi/
│   └── x86/
└── META-INF/
    ├── CERT.RSA
    ├── CERT.SF
    └── MANIFEST.MF

Как уменьшить APK?

Оптимизация ресурсов. Удалите ненужные ресурсы, используйте форматы изображений с меньшим размером (WebP), не включаете ресурсы для всех разрешений экранов, если они не нужны.

Использование ProGuard и R8. Удалите неиспользуемый код и оптимизируйте его. Обфусцируй и сожми код.

Разделение APK на модули. Создать разные APK для различных архитектур процессоров или разрешений экрана.

Оптимизация библиотек. Удалите лишние зависимости.

Упрощение кода. Не оставляете неиспользуемый код в проекте.

Сжатие файлов. Используйте инструменты для сжатия ресурсов и файлов, такие как pngcrush или jpegoptim для изображений.

Использование shrinkResources. Этот флаг удаляет неиспользуемые ресурсы из APK.

Использование Android App Bundle. Позволяет Google Play автоматически генерировать APK для различных конфигураций устройств. Это помогает сократить размер скачиваемого APK для конечного пользователя.

Как взломать APK?

• Распаковать APK. Сразу можно посмотреть AndroidManifest (exported=true). Запустить компоненты. Узнать установлено ли приложение на телефон.

• Просмотреть strings.xml. Там могут лежать ключи.

• Украсть сертификат SSL Pinning из папки raw.

• Перевести .dex в .jar утилитой dex2jar.

• Найти методы Retrofit и получить доступ к коду всех методов работы с сервером.

• Включить debug-меню если разработчики не удаляют его код из release-версии.

.dex

DEX файл – результат компиляции кода Android-приложения. Расшифровывается как Dalvik Executable, но несмотря на это используется и на устройствах со средой исполнения ART. В Java-программах каждый .java файл компилируется в отдельный .class файл. DEX аналогичен файлам .class, но содержит байткод всего приложения (или части приложения в случае Multidex), а не одного класса.

Проблема 64k методов

Это ограничение на количество методов в одном .dex-файле. Максимальное количество методов в .dex-файле равно 65536. На ранних версиях Андроида приложение могло иметь только один .dex-файл. Проблема 64К ограничивала количество методов в приложении. Один класс в Java может иметь максимум 64К методов. В Андроиде .dex-файл сделан по образу .class и поэтому наследует это ограничение. Причина ограничения в том, что под индексы ссылок на методы в java- и dalvik-байткоде выделено 16 бит. Т.е. максимальное число 2^16 = 65536. На ранних версиях Андроида единственным решением было уменьшение количества методов. Для этого использовался Proguard. Сейчас проблема решается включением Multidex. В этом случае приложение может иметь более одного .dex-файла.

AAB (Android App Bundle)

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

Zygote

Ключевой процесс, который служит для создания новых процессов приложений. Он работает как предзагруженный процесс, из которого создаются копии для каждого приложения с помощью механизма форка (forking). Это позволяет значительно ускорить запуск приложений и сэкономить память.

Инициализация. При загрузке системы Zygote запускается и загружает все необходимые библиотеки, компоненты и классы, общие для всех приложений Android.

Fork (разветвление). Когда нужно запустить новое приложение, Zygote делает “fork” — создаёт новый процесс, который является копией самого процесса Zygote. Это копирование позволяет новому процессу использовать уже загруженные системные ресурсы.

Оптимизация. За счёт предзагрузки общих ресурсов и быстрого разветвления процесс Zygote существенно ускоряет запуск приложений и снижает использование оперативной памяти, так как часть данных (например, классы и библиотеки) остаётся общей для всех приложений.

Приоритеты процессов

  1. Foreground Process (Процесс переднего плана): Наивысший приоритет. Содержит активные пользовательские приложения и процессы, которые напрямую взаимодействуют с пользователем. Всегда остается в памяти и не подвержен убийству системой при нехватке ресурсов.
  1. Visible Process (Процесс видимого приложения): Высокий приоритет. Содержит процессы приложений, которые видимы пользователю, но не активны. Может быть убит системой, если ей нужно освободить память, но только после более низко приоритетных процессов.
  1. Service Process (Процесс службы): Средний приоритет. Содержит процессы, которые выполняют фоновую работу (например, службы, выполняющие долгие задачи). Убиваются только в последнюю очередь, если система нуждается в освобождении ресурсов.
  1. Background Process (Процесс фонового приложения): Низкий приоритет. Содержит приложения, которые не видны пользователю и не выполняют активные задачи. Могут быть убиты системой в первую очередь при нехватке памяти.
  1. Empty Process (Пустой процесс): Наименьший приоритет. Содержит процессы, которые больше не используются и освободили всю память. Убиваются первой, когда системе нужно освободить ресурсы.
CI/CD

Непрерывная интеграция (Continuous Integration, CI) и непрерывная поставка (Continuous Delivery, CD) представляют собой культуру, набор принципов и практик, которые позволяют разработчикам чаще и надежнее развертывать изменения программного обеспечения. Цель CI — обеспечить последовательный и автоматизированный способ сборки, упаковки и тестирования приложений. Непрерывная поставка начинается там, где заканчивается непрерывная интеграция. Она автоматизирует развертывание приложений в различные окружения.

Doze Mode

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

Активирование. Doze Mode активируется, когда устройство находится в состоянии покоя. Это происходит, когда экран выключен, и устройство не перемещается в течение определенного времени.

Режимы работы. Когда устройство находится в покое в течение более длительного времени, Doze Mode переходит в более строгий режим экономии энергии, при котором доступ к сети и частичным пробуждениям ограничен еще больше.

Ограничение фоновых операций. Doze Mode ограничивает фоновые операции, такие как синхронизация данных и сетевые запросы, чтобы снизить энергопотребление.

Ограничение активности. Приложения не могут выполнять фоновую работу или получать сообщения до тех пор, пока не произойдут запланированные интервалы пробуждения (standby maintenance windows).

Смарт-уведомления. Приложения могут обрабатывать уведомления в рамках ограничений Doze Mode, но время их доставки может быть отложено до следующего пробуждения устройства.

Пробуждение устройства. Doze Mode не влияет на высоко приоритетные события, такие как входящие вызовы и сообщения, которые могут пробудить устройство. Также может быть пробуждено с помощью действий пользователя, таких как нажатие кнопок или взаимодействие с экраном.

Настройки и исключения. Пользователи могут управлять некоторыми аспектами Doze Mode через настройки устройства, но основное поведение управляется системой. Приложения могут запрашивать исключения от Doze Mode через механизм “whitelist”, если они требуют постоянного фона для критичных задач (например, для приложений для отслеживания местоположения или уведомлений о сообщениях).

Старые устройства. На устройствах, работающих под управлением Android 5.1 или ниже, аналогичные функции экономии энергии называются “App Standby” и имеют более ограниченные возможности по сравнению с Doze Mode.

• Если ваше приложение не выполняет критически важные задачи в фоновом режиме, оно может быть приостановлено в Doze Mode, и система выполнит фоновые операции (такие как синхронизацию данных) только в рамках определенных интервалов. Это помогает сохранить заряд батареи и улучшить общую производительность устройства.

AIDL

Android Interface Definition Language. Язык межпроцессного взаимодействия. Разные процессы не имеют общего пространства памяти, поэтому данные между процессами передаются через сообщения. Интерфейс передачи данных создается на языке AIDL. AIDL поддерживает передачу объектов Parcelable и Serializable.

ANR

Application Not Responding – системный диалог для пользователя, когда приложение зависает. Отображается если: не поступает ответа от UI (нажатие на экран) за 5 сек, broadcastReceiver не завершил выполнение за 10 сек. Частая причина ANR – IO-операции в главном потоке (чтение/запись в бд).

Android Build. Вопросы на собесе
  1. Для чего нужен ProGuard?
  1. Что такое проблема 64k методов?
  1. Разница между implementation и api?
  1. Как уменьшить APK?
  1. Что такое Doze Mode?
  1. Различие между compileSdk и targetSdk?
  1. Уменьшилась скорость сборки проекта, в чем может быть проблема?
  1. Что происходит когда пользователь нажимает на иконку приложения и до вызова Application.onCreate?

    Когда пользователь нажимает на иконку приложения, система создает новый процесс через форк процесса Zygote, загружает ресурсы и компоненты приложения, создает объект Application, а затем вызывает метод Application.onCreate().

  1. Как ускорить холодный старт приложения?

    Отложить инициализацию тяжелых ресурсов в Application.onCreate, делать инициализацию ленивой, использовать библиотеку AppStartup, оптимизовать код с помощью ProGuard и R8.

  1. В чем преимущества многомодульности?

    Многомодульность в Android улучшает структуру проекта, ускоряет сборку, облегчает повторное использование кода и тестирование, а также упрощает управление зависимостями и параллельную разработку.

  1. Что такое ANR?

    App nothing to request

    Application not responding

    Application nobody request

    Android not responding