SDK
- Плагины для IDE
- Инструменты для сборки
- Инструменты для отладки
- Библиотеки
- Образы эмуляторов
Android Studio
- Представлен в 2013, как замена Eclipse
- Система сборки gradle
- Отображение UI
- Интегрирован c Goole Developer Console
- Встроенный профайлер памяти, CPU, Network
- Поддержка систем контроля версий (git, svn и др.)
- Поддержка нескольких языков программирования
- Поддержка специфичных конструкций и компонент
Gradle
- Построена на принципах apache ant и apache maven.
- DSL использует Groovy (Kotlin) вместо XML
- Позволяет расширять сборку собственными функциями
- Использует направленный ацикличный граф для определения порядка выполнения задач
- Считается более гибким и пригодным для сборки Android приложений
Gradle. Запуск
- Запуск через файл gradle.
- Запуск через файл gradlew, где w означает wrapper (обертка).
gradle init
Gradle
- Задача (task) является основным компонентом процесса сборки в файле билда.
- Задачи представляют собой именованные наборы инструкций билда.
- По сравнению с традиционными возможностями объявления операций билда, связанных зависимостями, задачи Gradle являются полнофункциональными объектами, которыми вы при желании можете управлять программно.
Gradle. Объявление задачи
task hello
Список задач
./gradlew tasks // все задачи
./gradlew subprojectName:tasks --all // все задачи для подпроекта,
// в том числе второстепенные
Gradle. Объявление задачи
Результат
------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------
Build Setup tasks
-----------------
init - Initializes a new Gradle build. [incubating]
wrapper - Generates Gradle wrapper files. [incubating]
Help tasks
----------
dependencies - Displays all dependencies declared in root project '__project'.
dependencyInsight - Displays the insight into a specific dependency in root project '__project'.
help - Displays a help message
projects - Displays the sub-projects of root project '__project'.
properties - Displays the properties of root project '__project'.
tasks - Displays the tasks runnable from root project '__project'.
Other tasks
-----------
hello
Gradle. Добавление простейшей операции
task hello << {
println 'hello, world'
}
- Операторы, такие как << («сдвиг влево» из Java), могут быть перегружены в Groovy для изменения поведения в зависимости от объектов с которыми они работают.
- В данном случае << перегружен в Gradle для добавления блока кода в список операций, которые выполняет задача.
Gradle. Добавление простейшей операции
Существует гибкая возможность добавления кода операции аддитивным способом, ссылаясь на объект созданной задачи:
task hello
hello << {
print 'hello, '
}
hello << {
println 'world'
}
./gradlew hello
:hello
hello, world
BUILD SUCCESSFUL
Total time: 1.916 secs
Gradle. Конфигурация задачи
task initializeDatabase
initializeDatabase << {
println 'connect to database'
}
initializeDatabase << {
println 'update database schema'
}
initializeDatabase {
println 'configuring database connection'
}
./gradlew initializeDatabase
configuring database connection
:initializeDatabase
connect to database
update database schema
BUILD SUCCESSFUL
Total time: 3.088 secs
Gradle. Конфигурация задачи
- Для обозначения блока кода между парой фигурных скобок, в Groovy используется термин «замкнутое выражение» или «замыкание» (closure).
- Функции-замыкания подобны объектам, которые можно передавать методу как параметр или присваивать переменной, с возможностью последующего выполнения.
Gradle. Конфигурация задачи
- Замыкание, добавленное к имени задачи без оператора сдвиг влево совсем не добавляет новую операцию.
- Добавился блок конфигурации.
- Конфигурационный блок задачи выполняется во время конфигурационной фазы жизненного цикла Gradle, которая предшествует фазе выполнения, во время которой выполняются операции задачи.
Gradle. Конфигурация задачи
- Каждый раз, когда Gradle запускает билд, процесс проходит через три фазы жизненного цикла: инициализация, конфигурация и выполнение.
- Выполнение — фаза, во время которой задачи билда выполняются в порядке, указанном в настройках их зависимостей.
- Конфигурация — фаза в которой объекты задачи собираются во внутреннюю объектную модель, обычно называемую направленным ациклическим графом.
- Инициализация — фаза, в которой Gradle принимает решение, какие объекты будут принимать участие в билде.
Gradle. Конфигурация задачи
- Конфигурационный блок — подходящее место для присвоения значений переменных и структур данных, которые используются операцией задачи в дальнейшем
- Структура конфигурации даёт вам возможность превратить задачи вашего билда в сущности развитой объектной модели, заполненные информацией о билде.
- В этом и состоит отличие задач Gradle от простого набора операций билда, которые выполняются в определённой последовательности.
Gradle. Конфигурация задачи
- Без такого отличия между конфигурацией и операцией, пришлось бы усложнять настройки зависимостей, что привело бы к потере надёжности и к снижению выразительности средств для связывания основных структур данных билда.
- При запуске Gradle-файла, конфигурационный код билда выполняется полностью, независимо от того, будет ли какая-либо из задач запускаться в фазе выполнения.
Процесс загрузки ОС Android
Процесс загрузки ОС Android
- Bootrom — это небольшой кусочек защищенной от записи флеш-памяти, встроенный в процессорный чип. Он содержит самый первый код, который выполняется процессором при его включении. Далее, он запускает BootLoader.
- BootLoader выполняет первичный запуск специфичных настроек перед запуском ядра. То есть дословно, копирует файлы в рабочую память устройства и передает управление коду, расположенному в разделе boot, что по сути есть ядро Linux.
Android Linux
- Ядро Linux обеспечивает такие низкоуровневые вещи, как управление памятью
- Защиту данных
- Поддержку мультипроцессности и многопоточности
- Здесь нет ничего от проекта GNU, не используется X.Org, ни даже systemd
- Все эти компоненты заменены аналогами, более приспособленными для использования в условиях ограниченной памяти, низкой скорости процессора и минимального потребления энергии
Android Linux
- Модификации ядра:
- добавлено несколько небольших компонентов
- ashmem (anonymous shared memory)
- Binder driver
- wakelocks (управление спящим режимом)
- low memory killer
Процесс загрузки ОС Android
- Ядро запускает настройку кэша, защищенную память, планировщик задач и загружает драйверы. Когда ядро завершит настройку и запуск своих подсистем, он первым делом запустить корневой и самый главный процесс init(). Все процессы запускаемые после него являются дочерними.
Процесс загрузки ОС Android
- init()
- подключает директории /sys, /dev, /proc
- запускает службы(daemon), которые указаны в файле init.rc
- Например, Service Manager, Media Server.
- Формат init.rc достаточно простой и по сути представляет собой набор команд, разделенных на блоки.
- Запуск среды выполнения Android путем запуска службы Zygote
Процесс загрузки ОС Android
- Zygote ответственен за инициализацию, старт системных служб, запуск и остановку пользовательских приложений и многие другие задачи.
- запускается с помощью приложения /system/bin/app_process
- код которой располагается в разделяемой библиотеке /system/lib/libandroid_runtime.so
- Zygote получит управление, он начинает формирование среды исполнения Java-приложений с помощью загрузки всех Java-классов фреймворка.
Процесс загрузки ОС Android
- system_server
- Включает в себя большинство высокоуровневых (написанных на Java) системных сервисов.
- В том числе Window Manager, Status Bar, Package Manager и, что самое важное, Activity Manager.
Процесс загрузки ОС Android
- Activity Manager
- Zygote открывает сокет /dev/socket/zygote и уходит в сон.
- Запущенный ранее Activity Manager посылает широковещательный интент Intent.CATEGORY_HOME, чтобы найти Launcher-приложение, отвечающее за формирование рабочего стола.
- Zygote, в свою очередь, форкается и запускает Launcher-приложение поверх виртуальной машины.
- На экране появляется рабочий стол, найденный Activity Manager и запущенный Zygote, и статусная строка, запущенная system_server в рамках службы Status Bar.
Запуск «своего» приложения.
Запуск «своего» приложения.
- После нажатия по иконке приложения Launcher пошлет интент с именем этого приложения, его примет Activity Manager и передаст команду на старт приложения демону Zygote.
- Zygote получает запрос на старт приложения от Activity Manager, он не запускает новую виртуальную машину, а просто форкается, то есть копирует самого себя и затем запускает поверх полученной копии виртуальной машины нужное приложение.
- Копия ART/Dalvik VM создаёт главный поток приложения (MainThread).
APK файл (Android Package)
- Manifest
- Resources
- Classes.dex
APK файл (Android Package)
- Java код (.java).
- Байт код (.class). Получаем с помощью javac.
- Другие байт коды используемых библиотек.
- Соединяем в файл classes.dex (Dalvik executable). Получаем с помощью утилиты dex.
- Соединяем AndroidManifest.xml, classes.dex и ресурсы (изображения, аудио файлы, видео файлы и др) в файл apk.
- С помощью утилиты aapt.
Dalvik
- Dalvik Virtual Machine (DVM) — виртуальная Java машина, разработанная как часть мобильной платформы Android.
- Cреда для выполнения компонентов операционной системы Android и пользовательских приложений.
- Каждый процесс выполняется в своём, изолированном адресном пространстве.
- Когда пользователь запускает приложение (либо операционная система запускает один из своих компонентов), ядро виртуальной машины Dalvik (Zygote Dalvik VM) создает отдельный, защищенный процесс в общей памяти, в котором непосредственно разворачивается VM, как среда для запуска приложения.
- Android выглядит как набор виртуальных машин Dalvik, в каждой из которых исполняется приложение.
Dalvik
- Использует архитектуру на основе регистров: структура данных, куда помещаются методы, основана на регистрах процессора. За счет отсутствия операций POP и PUSH, команды в регистровой виртуальной машине выполняются быстрее аналогичных команд стековой виртуальной машины.
- Исполняет байт-код собственного формата: Android dexer преобразует class-файлы в формат .dex, оптимизированные для выполнения на Dalvik VM. В отличие от class-файла, dex-файл содержит сразу несколько классов.
jvm vs dvm
Android Dexer
- Процесс преобразования Java байткода в .dex байткод для Android Runtime является ключевым шагом в создании APK.
- Напрямую влияет на время сборки приложения, на размер файла .dex и производительность во время выполнения.
- dex-файл содержит сразу несколько классов.
- Изначально, class-файлы преобразовывались в dex-файлы с помощью встроенного DX-компилятора.
- Далее, компилятором по умолчанию стал D8.
- По сравнению с DX-компилятором, D8 компилирует быстрее и выводит dex-файлы меньшие по размеру, при этом обеспечивая более высокую производительность приложения во время исполнения.
- Полученный таким образом байт-код dex подвергается минификации с помощью open-source утилиты ProGuard.
D8
R8
- Следом за D8 пришел R8, который, по сути, является тем же D8, только с дополнениями.
- Proguard больше не используется для оптимизации кода во время компиляции.
- Вместо этого плагин работает по умолчанию с R8, который сам выполняет Code shrinking, Optimisation и Obfuscation.
R8 и сокращение кода
- приложения используют сторонние библиотеки, такие как Jetpack, Gson, Google Play Services.
- Когда мы используем одну из этих библиотек, часто в приложении используется только малая часть каждой отдельной библиотеки.
- Без Code shrinking, весь код библиотеки сохраняется в вашем приложении.
- для улучшения читаемости и удобства поддержки приложения разработчики используют подробный код.
- Например, могут быть использованы значимые имена переменных и шаблон проектирования для того, чтобы другим было удобнее разобраться в коде.
- R8 позволяет существенно уменьшить размер приложения, оптимизируя размер даже того кода, который действительно используется приложением.
R8 и сокращение кода
ART vs DVM в Android
- DVM была спроектирована именно для мобильных устройств
- использовалась как виртуальная
машина для запуска андроид приложений вплоть до Android 4.4 Kitkat.
- Начиная с этой версии, ART был представлен как среда выполнения
- в Android 5.0 (Lollipop) ART полностью заменил Dalvik.
- Основное явное отличие ART от DVM состоит в том, что ART использует AOT компиляцию, а DVM — JIT компиляцию.
- Не так давно ART начал использовать гибрид AOT и JIT.
DVM
- Использует JIT компиляцию: всякий раз при запуске приложения,
- компилируется та часть кода, которая необходима для выполнения приложения. Остальная часть кода компилируется динамически. Это замедляет запуск и работу приложений, но уменьшает время установки.
- Ускоряет загрузку устройства, поскольку кеш приложения создается во время выполнения.
- Приложения, работающие на DVM, требуют меньше памяти, чем те, которые работают на ART.
- Уменьшает резерв батареи, увеличивая нагрузку на CPU.
- Dalvik является “устаревшим” и не используется на андроид версиях выше 4.4.
DVM
ART
- Использует AOT компиляцию, то есть компилирует весь код во время установки приложения. Это ускоряет запуск и работу приложений, но требует большего времени установки.
- Замедляет загрузку устройства, так как кеш создается во время первой загрузки.
- Ввиду использования подхода AOT компиляции, требует больше памяти в сравнении с приложениями на DVM.
- Увеличивает резерв батареи, сокращая работу процессора из-за отсутствия компиляции при выполнении приложений.
- Улучшенная Garbage Collection или сборка мусора. Во времена использования Dalvik, сборщики мусора должны были осуществить 2 прохода по куче (heap), что и приводило к плохому UX. В случае с ART, такой ситуации нет: он чистит кучу один раз для консолидации памяти.
ART
DVM vs ART
AndroidManifest.xml
- Разрешения
- Описание всех компонент: application, activity, service, receiver.
- Дополнительная информация.
- Activity: визуальная часть приложения, точка входа
- Application: класс приложения, используется как глобальный синглтон.
- Service: нет интерфейса, работает в фоне.
- Receiver: системные и пользовательские оповещения.
manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="string"
android:versionCode="string"
android:versionName="string"
android:installLocation=[ "auto" | "internalOnly" | "preferExternal" ]
>
</manifest>
manifest
- package - имя пакета приложения в стиле Java, должно быть уникальным
- android:versionCode - версия приложения, нужна для обновления
- android:versionName - версия приложения, которая показывается пользователя
- android:installLocation - куда ставить приложение.
permission
<permission
android:description="string"
android:icon="string"
android:label="string"
android:name="string"
android:protectionLevel="string"
/>
permission
- android:name - "android.permisstion.INTERNET"
- android:icon - иконка, для пользователя
- android:label - название, для пользователя
- android:description - описание, для пользователя
- android:protectionLevel - описание риска
application
- Большое количество настроек.
- android:name - Название приложения
- android:theme - набор параметров, которые применяются ко всему приложению, содержит базовые цвета приложения, стили для отрисовки всех компонентов приложения и различные настройки.
- android:icon - иконка приложения.
activity
- Описывает параметры к экрану (Activity подкласс). Все экраны должны быть представлены в манифесте.
- android:name - название класса (например, com.example.project.ExtracurricularActivity)
- android:screenOrientation - ориентация экрана (например, портретная или альбомная).
- android:lauchMode - описание, как экран должен запускаться (например, singleTop).
- android:label - надпись над экраном.