Как написать программу или игру на Android: разработка приложения с нуля

Как написать программу или игру на Android: разработка приложения с нуля Полезное

Разработка приложения для Android — это цепочка из четырех шагов: написать код (сегодня по умолчанию на Kotlin), собрать его в Android Studio в установочный файл, запустить на эмуляторе или телефоне и подписать сборку для публикации в магазине. Ниже — дорожная карта до конкретного артефакта: простой игры «Угадай число», которая работает на вашем телефоне и готова к загрузке в Google Play или RuStore.

Логика игры проверена 24.09.2026 прогоном на JVM; интерфейс рассчитан на шаблон Empty Activity актуальной Android Studio с Jetpack Compose.

Четыре слова, которые путают новички

  • Android Studio — среда разработки (IDE) от Google: редактор, сборка, эмулятор, отладчик.
  • Android SDK — набор библиотек и утилит под конкретные версии Android; Android Studio скачивает его сама.
  • Gradle — система сборки: превращает исходники в APK или AAB. Настройки лежат в файлах build.gradle.kts.
  • APK и AAB. APK — файл, который ставится на устройство напрямую. AAB (Android App Bundle) — формат для загрузки в Google Play: магазин сам нарезает из него APK под конкретные устройства. Для новых приложений в Google Play обязателен AAB.

Какой язык и инструмент выбрать

Главный критерий — что вы делаете: обычное приложение или игру, только Android или сразу несколько платформ.

Задача Что взять Когда иначе
Обычное приложение только под Android Kotlin + Jetpack Compose в Android Studio Поддержка старого проекта на Java и XML-разметке
Приложение для Android и iOS одной кодовой базой Kotlin Multiplatform или Flutter (Dart) Нужны глубокие платформенные функции — часть кода все равно нативная
Простая 2D-игра (головоломка, кликер) Kotlin + Compose или Canvas, без движка Появляется физика, анимации, много уровней — берите движок
2D/3D-игра с физикой и сценами Unity (C#) или Godot (GDScript/C#) Тяжелая 3D-графика — Unreal Engine (C++)
Прототип без программирования Конструктор приложений Нужна своя логика и контроль над кодом

Kotlin Google с 2019 года называет основным языком для Android (Kotlin-first): на нем новая документация, примеры и библиотеки Jetpack. Java по-прежнему поддерживается и встречается в старых проектах, но новый проект логичнее начинать на Kotlin. Python и C++ не заменяют их: C++ через NDK нужен для производительных частей (движки, обработка звука), а на Python нативные Android-приложения почти не пишут.

Про конструкторы без кода есть отдельный разбор: конструкторы для Android. Здесь — путь с кодом.

Дорожная карта: от установки до публикации

  1. Установить Android Studio с официального сайта Android для разработчиков. На первом запуске мастер скачает Android SDK и образ эмулятора. Комфортно работать на машине с 16 ГБ оперативной памяти и SSD.
  2. Создать проект: New Project -> Empty Activity. В актуальных версиях этот шаблон сразу на Kotlin и Compose; шаблон на XML-разметке называется Empty Views Activity.
  3. Заполнить поля: Name (Guess Number), Package name (com.example.guessnumber, для публикации замените example на свой домен или ник), Minimum SDK — оставить предложенный по умолчанию.
  4. Дождаться окончания Gradle Sync (первый раз скачиваются зависимости, нужен интернет).
  5. Написать логику и экран (код ниже).
  6. Запустить на эмуляторе или телефоне кнопкой Run.
  7. Собрать подписанный AAB и загрузить в магазин.

Реалистичный срок до первого своего приложения на телефоне при нуле опыта — несколько недель вечерних занятий, из них большая часть уходит на основы Kotlin.

Что лежит в проекте

  • app/src/main/AndroidManifest.xml — манифест: какие экраны (Activity) есть, какой открывается первым, какие разрешения нужны.
  • app/src/main/java/com/example/guessnumber/ — код на Kotlin (папка называется java по историческим причинам).
  • app/src/main/res/ — ресурсы: строки, иконки, цвета.
  • app/build.gradle.kts — настройки модуля: applicationId, minSdk, targetSdk, зависимости.
  • app/src/test/ — unit-тесты, которые запускаются на компьютере без эмулятора.

Пишем игру «Угадай число»

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

Шаг 1. Логика без Android

Создайте файл GuessLogic.kt рядом с MainActivity.kt и первой строкой поставьте тот же package, что в MainActivity.kt (например, package com.example.guessnumber), иначе экран не увидит функции. Ниже — содержимое без этой строки, чтобы его можно было запустить отдельно. Android-импортов в нем нет:

enum class Hint { LOW, HIGH, WIN, INVALID }

// Чистая логика игры: без Android-импортов, поэтому тестируется на обычной JVM
fun judge(secret: Int, input: String): Hint {
    val guess = input.trim().toIntOrNull() ?: return Hint.INVALID
    if (guess !in 1..100) return Hint.INVALID
    return when {
        guess < secret -> Hint.LOW
        guess > secret -> Hint.HIGH
        else -> Hint.WIN
    }
}

fun hintText(hint: Hint, attempts: Int): String = when (hint) {
    Hint.LOW -> "Мое число больше"
    Hint.HIGH -> "Мое число меньше"
    Hint.WIN -> "Угадали! Попыток: $attempts"
    Hint.INVALID -> "Введите целое число от 1 до 100"
}

fun main() {
    val secret = 42
    var attempts = 0
    for (input in listOf("50", "", "abc", "25", "42")) {
        val hint = judge(secret, input)
        if (hint != Hint.INVALID) attempts++
        println("\"$input\" -> ${hintText(hint, attempts)}")
    }
}

Функция main нужна только для проверки вне Android (в любом Kotlin-окружении). В проекте ее лучше убрать, а те же проверки оформить unit-тестом в app/src/test/. Вывод:

"50" -> Мое число меньше
"" -> Введите целое число от 1 до 100
"abc" -> Введите целое число от 1 до 100
"25" -> Мое число больше
"42" -> Угадали! Попыток: 3

Пустая строка и abc не считаются попытками, поэтому победа засчитана с третьей настоящей попытки.

Ошибка, на которой падает каждое второе первое приложение

Соблазнительно написать короче — input.toInt():

fun main() {
    val input = ""          // пользователь нажал кнопку с пустым полем
    val guess = input.toInt()
    println(guess)
}

Результат (первые строки стека; номера строк в Integer.java зависят от версии JDK):

Exception in thread "main" java.lang.NumberFormatException: For input string: ""
    at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:68)
    at java.base/java.lang.Integer.parseInt(Integer.java:668)

На телефоне это выглядит как закрытие приложения с сообщением о сбое, а причина видна только в окне Logcat Android Studio. Исправление — toIntOrNull() с веткой для неверного ввода, как в judge выше. Любой ввод пользователя на Android проверяйте так же: пустое поле, лишние пробелы, слишком длинное число.

Шаг 2. Экран на Jetpack Compose

Замените содержимое MainActivity.kt (строку package оставьте свою):

package com.example.guessnumber

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp
import kotlin.random.Random

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MaterialTheme {
                Surface(Modifier.fillMaxSize()) { GuessScreen() }
            }
        }
    }
}

@Composable
fun GuessScreen() {
    var secret by rememberSaveable { mutableIntStateOf(Random.nextInt(1, 101)) }
    var attempts by rememberSaveable { mutableIntStateOf(0) }
    var input by rememberSaveable { mutableStateOf("") }
    var message by rememberSaveable { mutableStateOf("Я загадал число от 1 до 100") }

    Column(
        modifier = Modifier.padding(24.dp),
        verticalArrangement = Arrangement.spacedBy(12.dp)
    ) {
        Text(message, style = MaterialTheme.typography.titleMedium)
        OutlinedTextField(
            value = input,
            onValueChange = { input = it.filter(Char::isDigit).take(3) },
            label = { Text("Ваш вариант") },
            keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
            singleLine = true
        )
        Button(onClick = {
            val hint = judge(secret, input)
            if (hint != Hint.INVALID) attempts++
            message = hintText(hint, attempts)
            input = ""
            if (hint == Hint.WIN) {
                secret = Random.nextInt(1, 101)
                attempts = 0
            }
        }) { Text("Проверить") }
    }
}

Что должно получиться: заголовок «Я загадал число от 1 до 100», поле с цифровой клавиатурой и кнопка. После каждой попытки заголовок меняется на подсказку, после победы игра молча загадывает новое число.

Разбор ключевых мест:

  • setContent { ... } — точка, где Activity передает управление Compose.
  • rememberSaveable хранит состояние экрана и переживает поворот телефона. Обычный remember при повороте теряет значения: Activity пересоздается, и загаданное число сменилось бы посреди игры.
  • it.filter(Char::isDigit).take(3) — фильтр ввода в поле. Это удобство, а не замена проверки: judge все равно отсекает 0 и числа больше 100.
  • Для настоящего приложения с сетью и базой данных состояние выносят во ViewModel — это следующий шаг после первой игры.

Запуск на эмуляторе и телефоне

Эмулятор. Откройте Device Manager (в старых версиях — AVD Manager), создайте виртуальное устройство, скачайте образ системы и нажмите Run. На Windows для скорости нужна включенная аппаратная виртуализация.

Телефон. В настройках откройте «О телефоне» и 7 раз нажмите «Номер сборки» — появится раздел «Для разработчиков». Включите в нем «Отладку по USB», подключите кабель и подтвердите на телефоне ключ компьютера. Телефон появится в списке устройств рядом с кнопкой Run. С Android 11 доступна и отладка по Wi-Fi.

Из терминала то же делается так (в корне проекта):

./gradlew assembleDebug
adb install -r app/build/outputs/apk/debug/app-debug.apk

Если не получилось

Симптом Частая причина Что сделать
Gradle Sync падает на загрузке Нет интернета, прокси, блокировка репозитория Проверить сеть и прокси в Settings, повторить Sync
Ошибка про версию Java/JDK при сборке Проект собирается не тем JDK В настройках Gradle выбрать JDK, встроенный в Android Studio
Эмулятор не стартует или очень медленный Выключена виртуализация, мало памяти Включить виртуализацию в BIOS/UEFI, закрыть лишнее, взять образ попроще
Телефона нет в списке устройств Кабель только для зарядки, не подтвержден ключ Другой кабель, режим передачи файлов, подтвердить запрос на экране
Unresolved reference Нет импорта или опечатка в имени Alt+Enter на красном слове — Android Studio предложит импорт
Приложение закрывается при запуске Исключение в коде Открыть Logcat, найти первую строку с FATAL EXCEPTION и Caused by

Подпись и публикация

Магазины принимают только подписанную сборку. В Android Studio: Build -> Generate Signed App Bundle or APK -> Android App Bundle, затем создать хранилище ключей (keystore) и ключ. Результат — файл .aab в папке app/release или app/build/outputs/bundle/release/.

С ключом стоит обращаться как с паролем от банка:

  • keystore и пароли не коммитить в Git; добавить файл в .gitignore, пароли хранить в менеджере паролей;
  • держать резервную копию keystore отдельно от рабочего компьютера;
  • в Google Play для новых приложений (с августа 2021 года, вместе с обязательным AAB) действует Play App Signing: ключ подписи приложения хранит Google, а у вас остается только ключ загрузки, который при потере можно сбросить через Play Console. Для RuStore и установки APK напрямую подпись целиком на вас: потерянный ключ означает, что обновить приложение под тем же именем пакета нельзя.

Google Play. Нужен аккаунт разработчика с разовым взносом. Для личных аккаунтов, созданных после 13.11.2023, перед выходом в открытый доступ обязателен закрытый тест: не менее 12 тестировщиков, подключенных непрерывно 14 дней. Приложение должно быть собрано под свежий targetSdk: с 31.08.2026 новые приложения и обновления для телефонов должны целиться не ниже чем в Android 16 (API 36), и Google ежегодно поднимает эту планку.

RuStore. Российский магазин приложений принимает APK и AAB; регистрация разработчика и модерация проходят отдельно от Google Play. Для аудитории в России это частый первый магазин, особенно когда оплата аккаунта Google Play затруднена.

Учтите: магазины могут отклонять слишком простые приложения без пользы для пользователя, поэтому «Угадай число» — учебный прогон всего пути, а не продукт.

Выводы

  • Новое Android-приложение сегодня пишут на Kotlin в Android Studio; шаблон Empty Activity сразу дает Jetpack Compose.
  • Логику стоит отделять от экрана: ее можно проверить обычным тестом без эмулятора.
  • Ввод пользователя всегда разбирается безопасно (toIntOrNull()), иначе приложение падает на пустом поле.
  • Для простой 2D-игры движок не нужен; для физики, сцен и 3D берут Unity, Godot или Unreal.
  • Публикация требует подписанного AAB, аккуратного хранения keystore и выполнения требований магазина.

Где применяется / связь с практикой

Освойте тему на практике

Игра «Угадай число» покрывает весь цикл — проект, логика, экран, запуск, подпись, — но в реальной работе к нему добавляются навигация между экранами, ViewModel, сеть, хранение данных и тесты. Системно пройти этот путь с разбором кода от практикующих разработчиков можно на курсе «Android-разработчик. Базовый уровень». Попробовать формат и задать вопросы преподавателям можно на бесплатных открытых уроках Otus.

FAQ

Можно ли разрабатывать под Android без мощного компьютера?
Писать и собирать код можно на слабой машине, но эмулятор требователен к памяти. Выход — отлаживать приложение сразу на своем телефоне по USB.

Нужен ли Mac для разработки под Android?
Нет. Android Studio работает на Windows, macOS и Linux. Mac обязателен только для сборки под iOS.

Можно ли написать приложение для Android прямо на телефоне?
Для учебных экспериментов есть мобильные редакторы кода, но полноценная сборка, отладка и публикация удобнее и надежнее в Android Studio на компьютере.

OTUS Журнал
Скидка 5% 12-19 октября на курсы (popup)
Бесплатные открытые уроки (поп-ап)