
Помню, как будто было вчера. На уроке раздается голос учителя: «Чтобы перейти в 11-ый, каждому из вас нужно реализовать свой проект. Творчество приветствуется!». Кажется, вот оно: знак сделать то, о чем уже давно подумывал, — создать собственное приложение! Защищаю идею перед классом и учителем, получаю одобрение. Впереди целый учебный год, казалось бы, у меня гора времени. Вот только я никогда в жизни не разрабатывал мобильные приложения…
Меня зовут Ваня, я Python-разработчик, а в свободное время пишу для блога MWS. Сегодня решил поделиться историей-воспоминанием, как в школьные времена приступил к разработке своего первого в жизни мобильного приложения, а потом дорабатывал его уже в университете. Тут не будет истории успеха в духе «я монетизировал проект и разбогател» и каких-то уникальных лайфхаков. Зато покажу на своем примере, что для создания приложения в качестве эксперимента не нужно знать все языки программирования и обладать суперскилами в разработке. Главное — не бояться пробовать. А еще те, кто только в начале своего пути, смогут научиться на моих ошибках и обратить внимание на детали, которые в свое время не учел я. Приступим!
Небольшая история небольшого приложения

Начало
Сентябрь 2020 года оказался для меня непростым: я перешел в новую школу, мне нужно было познакомиться с десятками новых людей, а еще — сделать собственное мобильное приложение (да-да, в это я сам добровольно вписался). Все бы ничего, но из навыков программирования в моем распоряжении были российский КуМир (учил его для сдачи ОГЭ) и пара синтаксических конструкций в Python. С таким багажом знаний далеко не уйдешь, но нужно было вертеться…
Сначала я решил провести анализ (да, подошел к вопросу серьезно), какие языки вообще используют для разработки приложений. Поисковики эксперты, к которым я обращался, привели меня к Java из-за кроссплатформенности. Кто я такой, чтобы с ними спорить? Сохранил в браузере с десяток закладок с обучениями программированию на этом языке и пошел чилить.
Прошло три месяца… Преподаватель спросил, как продвигается мой проект, и тут я чуть не провалился сквозь землю, ведь у меня не было сделано ни-че-го. Мне срочно был нужен хотя бы MVP. «Сегодня же начну», — сказал я себе. И реально начал.

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

Окей, цель есть. На чем писать приложение — понятно, пора приступать.
Как вы думаете, с чего я начал? Правильно, полез на YouTube. Мне нужно было разобраться со всем с основами языка Java (переменные, циклы), понять, как визуально создаются уровни и как их переключать, как сохранять прогресс и так далее. Пересмотрев множество роликов по разработке приложений на Java с нуля, я смог настроить Android Studio и даже запустить приложение с несколькими кнопками. Основа есть, теперь проработаем идею.
Если вы сфокусированы на тайм-менеджменте и используете для этого различные приложения, скорее всего, вы знакомы с Forest. Суть довольно проста: запускаете таймер — не трогаете телефон до окончания таймера — у вас вырастает дерево. Мне очень понравилась идея, что человек своими действиями может вырастить виртуальное дерево. Я взял ее за основу.
Идея в алгоритмах
В моем приложении пользователю не нужно ждать — ему нужно делать. Каждое выполненное задание — еще один шаг к большому и красивому, хоть и виртуальному, дереву. Из заданий было, например, экономить воду, прогуляться на природе, сортировать мусор, заняться йогой и так далее. Помните же, цель — понизить уровень стресса и бережно относиться к экологии?
Я решил запустить приложение на одну неделю, MVP все-таки. То есть у нас с вами 7 дней, 7 основных уровней:

Теперь мне нужно было нарисовать семь экранов. Изображение холмика будет на всех, а потом я буду обновлять только отображение дерева. На последних уровнях для разнообразия добавлю цветочек.
Я начал усердно рисовать мышкой каждый пиксель, ведь графического планшета у меня не было. Снимал себя со стороны на телефон, который приходилось крепить на пюпитре. Оказывается, его можно использовать не только для нот!

Рисовал по вечерам, вернувшись домой после школы. Иногда мы созванивались с моим другом и часы напролет обсуждали все на свете. Как-то он спросил меня: «Почему ты все рисуешь с нуля? Тебе ведь нужно быстро сделать прототип. Используй что-то готовое». И он был прав: я отлично умел все усложнять там, где не нужно. Пора было упрощать! Тем вечером мы вместе нашли готовые изображения деревьев от мало до велика. Мне оставалось только распределить их по порядку для всех семи уровней.
Итак, у меня образовалось семь классов по каждому на уровень и еще два для начала игры и финального сообщения.

В коде переход между уровнями удалось реализовать при помощи SWITCH/CASE:
switch(level) {
case 0:
try {
Intent intent = new Intent(MainActivity.this, FirstStageActivity.class);
startActivity(intent);
overridePendingTransition(0,0);
finish();
} catch (Exception e) {
// Empty
}
break;
case 1:
try {
Intent intent = new Intent(MainActivity.this, SecondStageActivity.class);
startActivity(intent);
overridePendingTransition(0,0);
finish();
} catch (Exception e) {
// Empty
}
break;
case 2:
try {
Intent intent = new Intent(MainActivity.this, ThirdStageActivity.class);
startActivity(intent);
overridePendingTransition(0,0);
finish();
} catch (Exception e) {
// Empty
}
break;
case 3:
try {
Intent intent = new Intent(MainActivity.this, FourthStageActivity.class);
startActivity(intent);
overridePendingTransition(0,0);
finish();
} catch (Exception e) {
// Empty
}
break;
case 4:
try {
Intent intent = new Intent(MainActivity.this, FifthStageActivity.class);
startActivity(intent);
overridePendingTransition(0,0);
finish();
} catch (Exception e) {
// Empty
}
break;
case 5:
try {
Intent intent = new Intent(MainActivity.this, SixthStageActivity.class);
startActivity(intent);
overridePendingTransition(0,0);
finish();
} catch (Exception e) {
// Empty
}
break;
case 6:
try {
Intent intent = new Intent(MainActivity.this, SeventhStageActivity.class);
startActivity(intent);
overridePendingTransition(0,0);
finish();
} catch (Exception e) {
// Empty
}
break;
}
Дальше нужно было продумать логику уровней.
Логика уровней
В каждом уровне было по три различных задачи. После того как пользователь их выполнял, он переходил на следующий уровень, но у меня никак не получалось связать между собой CheckedTextView и счетчик выполненных задач. Собрав всю свою смелость в кулак, я написал первый за все время вопрос на StackOverflow:

Оказалось, я запутался в области видимости переменных. Вместо локальной переменной для счетчика выполненных задач нужно было добавить приватную и вынести ее из метода onClick.
Переключение между задачами в уровне тоже сделал при помощи конструкции SWITCH/CASE:
private int i = 0;
private final String[] seasons = {"Послушать музыку", "Позаниматься спортом","Почитать книгу"};
@Override
public void onClick(View v) {
checkedTextView.toggle();
if(checkedTextView.isChecked()) {
checkedTextView.setChecked(false);
checkedTextView.setVisibility(View.INVISIBLE);
checkedTextView.setText(seasons[i]);
i++;
switch(i) {
case 1:
JobGood.setVisibility(View.VISIBLE);
new Handler().postDelayed(() -> JobGood.setVisibility(View.INVISIBLE),3 * 1000);
Task_Water.setVisibility(View.VISIBLE);
new Handler().postDelayed(() -> {
Task_Water.setVisibility(View.INVISIBLE);
checkedTextView.setVisibility(View.VISIBLE);
},8 * 1000);
break;
case 2:
FlowerMusic.setVisibility(View.VISIBLE);
new Handler().postDelayed(() -> {
FlowerMusic.setVisibility(View.INVISIBLE);
checkedTextView.setVisibility(View.VISIBLE);
},5 * 1000);
break;
case 3:
ActivitySport.setVisibility(View.VISIBLE);
new Handler().postDelayed(() -> {
ActivitySport.setVisibility(View.INVISIBLE);
Tree_Growing_Up_First_Stage.setVisibility(View.VISIBLE);
new Handler().postDelayed(() -> {
Tree_Growing_Up_First_Stage.setVisibility(View.INVISIBLE);
ThreeTasks.setVisibility(View.VISIBLE);
new Handler().postDelayed(() -> {
ThreeTasks.setVisibility(View.GONE);
checkedTextView.setVisibility(View.VISIBLE);
try {
Intent intent = new Intent(FirstStageActivity.this, SecondStageActivity.class);
startActivity(intent);finish();
overridePendingTransition(0,0);
} catch (Exception e) {
// Empty
}
},4 * 1000);
},3 * 1000);
},4 * 1000);
Tree1.setVisibility(View.INVISIBLE);
// Изменение дерева при переходе с одного уровня на другой
Tree2.setVisibility(View.VISIBLE);
break;
}
}
}
Нужна была мотивация — мне тоже, конечно, но в первую очередь играющему. Зачем ему вообще выполнять задания? Решение пришло такое: после каждого задания, помимо роста дерева, у него будет появляться карточка с интересным фактом. Я старался сделать так, чтобы каждая была уникального цвета.

Пока настраивал видимость на экране, заметил, что код часто дублируется. Сказывался недостаток опыта программирования и ну очень скромное знание Java.
Есть контакт
В конце концов пазлики начали складываться — и приложение заработало!
Смотреть

Защитился я успешно. Защита, кстати, проходила дистанционно, так что я постарался максимально это использовать. Например, чтобы продемонстрировать выполнение задания «Позаниматься спортом», проиллюстрировал все на своем примере со своими гантелями. Учителя инициативу оценили!
Благодаря проекту я смог спокойно перейти в 11 класс, а потом с ним же подался на участие в конференции. Но это не было финалом: история моего приложения продолжилась в университете.
2022 год — второй курс в университете
После успешного (и неожиданного) поступления в Бауманку я сместил весь мой фокус на учебу. Мне казалось, что я ничего не понимаю (сейчас в магистратуре тоже такое бывает) и нужно учиться, учиться и еще раз учиться.
Из иностранных языков я выбрал английский. И вот как-то раз, на одной из осенних пар, учитель спросил, не хочет ли кто-нибудь поучаствовать в инвестиционном проекте. Оказалось, каждый год на кафедре лингвистики проходит мероприятие на английском языке, похожее на Shark Tank, где инвесторы (старшекурсники) слушают выступления студентов младших курсов, которые представляют свои проекты. Для меня и моего проекта это было вторым дыханием. Я сразу вспомнил о своем приложении с деревом и решил участвовать.
Идея немного модернизировалась: теперь каждый листочек знаменовал собой выполненное задание. Рисунок потом можно было сохранить и, например, поделиться им в социальных сетях.

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

Есть такое понятие «поток», и это был он. Я, сам того не замечая, начал в красках описывать контекст и ситуации и погрузил аудиторию в небольшое приключение. Звучало это примерно так: «Представьте, что вы в саду, под ногами мягкая трава, вы чувствуете тепло, любуетесь солнцем, которое высоко-высоко горит в небе. А потом подходите к дереву и видите, как оно растет». Не помню, что там было еще, но слушателям понравилось. Потихоньку я подвел эту импровизированную историю к мобильному приложению.

После выступления я, наконец, выдохнул. Было волнительно, но все сложилось как надо. Чуть позже я разместил проект на GitHub и отложил его в далекий темный ящик.
А теперь расскажу, что во всем этом для меня было самое сложное.
С какими сложностями я столкнулся
Один в поле не воин
Фраза «Я сделал все в одиночку» звучит, конечно, классно, но стоит ли игра свеч? Задачи лучше делегировать — тогда и результат будет более сильным.
В свое время мне нужно было сфокусироваться на многих областях: разработка, тестирование, дизайн, формирование презентации, написание речи для выступления. Я не мог сделать все это так хорошо, как мне хотелось. Тогда моей целью было хотя бы сделать что-то работающее и успеть до дедлайнов, так что, можно сказать, я с ней справился. Но если я когда-нибудь еще возьмусь за мобильное приложение, я в первую очередь соберу команду.
Изучение языка
Мне нужно было быстро сделать MVP. Можете себе представить, что использовать язык программирования, который не знаешь, и пытаться разработать с его помощью что-то опупенное — так себе идея. Чтобы разобраться в языке, мне нужно было гораздо больше времени. Но я торопился, и столкнулся с кучей вытекающих из этого проблем. Да, ЯП чем-то похожи между собой, но писать небольшие скрипты на Python и мобильные приложения на Java — это два разных мира.
Дублирование кода
Ctrl+C/Ctrl+V было много. На каждом уровне приходилось скрывать все карточки, кроме трех для конкретного уровня. Поэтому в каждом классе можно было встретить примерно такие строчки:
final ImageView MorningTraining = findViewById(R.id.MorningTraining);
final ImageView BiggestFlower = findViewById(R.id.BiggestFlower);
final ImageView Tea = findViewById(R.id.Tea);
final ImageView Singing = findViewById(R.id.Sing);
final ImageView Goal = findViewById(R.id.Goal);
MorningTraining.setVisibility(View.INVISIBLE);
BiggestFlower.setVisibility(View.INVISIBLE);
Tea.setVisibility(View.INVISIBLE);
Singing.setVisibility(View.INVISIBLE);
Goal.setVisibility(View.INVISIBLE);
Я знал, что как-то это можно было решить. Но как — ответа не находил.
Игра тормозила
Есть такие приложения, в которых тык-тык — и красота. Действия выполняются плавно. У меня было не так — да, именно жирным шрифтом. Кнопки нажимались сразу, но приходилось ждать около секунды для прогрузки. Хотелось, чтобы отклик был быстрее.
Смотреть

Локализация
А я ее просто не учел! Мое приложение было сделано для русской аудитории. Но что, если кто-то не знает русский язык, но тоже хотел бы поиграть? Добавить бы еще английский и другие языки, но ведь тогда все карточки нужно было бы рисовать заново. Может, тогда лучше использовать не картинки, а какие-то другие элементы, в которых можно динамически менять текст?
В общем, о локализации желательно думать до начала разработки приложения.
Монетизация
Только в университете я придумал, как можно монетизировать приложение. Вариант А — реклама, вариант Б — сделать полную версию приложения платной. Но все это банально, а хотелось нащупать уникальную бизнес-модель. Этот момент я так и не проработал.
Конечно, если разрабатываешь приложение не в качестве школьного проекта или эксперимента, этот пункт нужно детально продумать.

На сегодня, пожалуй, все. Да, этот текст не о баснословном успехе или уникальном открытии — он о желании воплотить идею в реальность и пробовать что-то новое. Недостаток опыта или незнание языка программирования могут быть преградами, но, как говорят, глаза боятся — руки делают. Так что вот вам мой скромный совет: придумывайте и реализовывайте. Это не так сложно, как может казаться.
Буду рад, если напишете в комментариях о своих проектах — с удовольствием почитаю!
Комментарии (4)

AbitLogic
05.11.2025 19:58Не знаю какие там тенденции в Java, но не многовато ли дублирования кода, что никак не обобщить эти простыни?
Dhwtj
Прекратите хвастаться отсутствием знаний и опыта.