Как устроено Android-приложение

Android-приложение — это набор компонентов, ресурсов и манифеста, собираемых системой Gradle в APK, а современные приложения строятся вокруг одной Activity и экранов на Compose.
Суть: чтобы уверенно двигаться дальше, нужно понимать, из каких частей состоит проект, зачем нужен манифест и почему сегодня большинство приложений используют единственную Activity.

Когда вы создаёте проект в Android Studio, генерируется структура из нескольких ключевых частей. Папка src/main/java (или kotlin) содержит код. Папка res — ресурсы: строки, цвета, изображения, темы. Файл AndroidManifest.xml описывает приложение системе: какие компоненты в нём есть, какие разрешения нужны, какая Activity запускается первой. Файлы build.gradle.kts управляют сборкой и зависимостями.

  Структура проекта

  app/
   |-- src/main/
   |     |-- kotlin/...        код приложения
   |     |-- res/              ресурсы (строки, цвета, иконки)
   |     '-- AndroidManifest.xml
   '-- build.gradle.kts        зависимости и настройки сборки

Компоненты приложения

Исторически Android выделяет четыре типа компонентов. Activity — экран с интерфейсом. Service — фоновая работа без UI. BroadcastReceiver — реакция на системные события. ContentProvider — обмен данными между приложениями. Для начинающего важнее всего Activity: именно она показывает интерфейс пользователю.

Современный подход — single-activity: приложение использует одну Activity, а переходы между экранами реализуются навигацией внутри Compose. Это упрощает управление состоянием и жизненным циклом по сравнению со старым подходом «много Activity».

Манифест

Манифест — это «паспорт» приложения. Система читает его перед запуском, чтобы понять, что приложение умеет и что ему нужно.

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-permission android:name="android.permission.INTERNET" />
    <application android:label="Моё приложение">
        <activity android:name=".MainActivity" android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

Как работает под капотом

Когда вы нажимаете «Запустить», Gradle компилирует Kotlin в байт-код, упаковывает его вместе с ресурсами и манифестом в APK (или AAB для публикации), подписывает и устанавливает на устройство. Система при запуске находит Activity с фильтром LAUNCHER и стартует её. Разрешения вроде доступа в интернет объявляются в манифесте, а опасные (камера, геолокация) дополнительно запрашиваются у пользователя во время работы.

Gradle и зависимости

Подключение библиотеки сводится к строке в build.gradle.kts и синхронизации проекта. Современные проекты держат версии в каталоге libs.versions.toml, но идея та же.

# пример объявления зависимости и сборки из консоли
./gradlew assembleDebug   # собрать debug-сборку
./gradlew installDebug    # установить на подключённое устройство

Частые ошибки

Забыть про exported. Начиная с Android 12, Activity с intent-filter обязана иметь явный android:exported, иначе приложение не соберётся.

Не объявить разрешение. Сетевой запрос без INTERNET в манифесте просто не пройдёт.

Плодить Activity. Новички делают по Activity на экран; современный подход — одна Activity и навигация в Compose.

Best practices

  • Используйте архитектуру single-activity с навигацией внутри Compose.
  • Храните версии зависимостей централизованно (version catalog).
  • Опасные разрешения запрашивайте в рантайме, а не только в манифесте.
  • Все пользовательские строки выносите в ресурсы, а не хардкодьте в коде.

Чтобы прочувствовать роль манифеста как «декларации возможностей», смоделируем проверку разрешений на Python. Запустите врезку.

# Аналог проверки разрешений по манифесту
manifest_permissions = {'INTERNET', 'CAMERA'}

def can_do(action_permission):
    return action_permission in manifest_permissions

for need in ['INTERNET', 'LOCATION', 'CAMERA']:
    ok = can_do(need)
    print(need, '->', 'разрешено' if ok else 'НЕТ в манифесте')

Попробуй сам ▶ — добавьте LOCATION в набор разрешений и посмотрите, как меняется результат. В Android аналогичную проверку делает система, читая манифест.

Итог: Android-приложение — это код, ресурсы и манифест, собираемые Gradle. Современная архитектура опирается на одну Activity и Compose. Дальше мы разберём, как Activity живёт во времени.

Проверьте себя
1. Зачем нужен файл AndroidManifest.xml?
AЧтобы хранить исходный код приложения
BЧтобы описать системе компоненты приложения, нужные разрешения и стартовую Activity
CЧтобы рисовать пользовательский интерфейс
DЧтобы подключать библиотеки
2. Что характерно для современной архитектуры single-activity?
AКаждый экран — это отдельная Activity
BПриложение использует одну Activity, а переходы между экранами делает навигация в Compose
CActivity вообще не нужна
DВсе экраны хранятся в манифесте