
Недавно наткнулся на новость о том, что количество приложений в Google Play Store сократилось на 47%.
Я сам энтузиаст разработки под Android и последние 5 лет работал над альтернативой для Google Play Music и Podcast под названием MusicSync. Так что, будучи близким к теме человеком, мне захотелось поделиться своим опытом обслуживания приложений и заодно пояснить, почему меня эта новость нисколько не удивила.
У меня есть несколько сторонних проектов, базирующихся на бэкенд-сервере с ограниченным веб-интерфейсом, и их обслуживание требует намного меньше усилий.
Если же говорить о приложении Android, то обслуживать его в качестве хобби-проекта гораздо хлопотнее. Вот некоторые из проблем, с которыми мне приходилось сталкиваться:
Java vs Kotlin
Если вы начинаете разработку под Android в 2025, то Kotlin явно станет предпочтительным языком. Но что, если вы обслуживаете хобби-проект, написанный на Java? В этом случае вы столкнётесь с проблемами несовместимости, когда обнаружите, что ваши зависимости переписывают на Kotlin.
Если ваш код зависит от библиотеки, использующей корутины Kotlin или опирающейся на suspend-функции, то вам придётся искать обходной путь или переписывать своё приложение на Kotlin.
Функциональность Jetpack Compose, официальной библиотеки Google UI для Android, из Java абсолютно недоступна.
Могу представить, что вы начали разработку на Kotlin, затем столкнулись с кучей вопросов на StackOverflow, написанных для аудитории Java, и были вынуждены переводить их в равнозначный код Kotlin.
Google вносит в свои библиотеки критические изменения
Компания Google славится своей привычкой вносить в библиотеки Android критические изменения. Ниже я перечислил некоторые библиотеки, которые я использовал в своём приложении, и проблемы, с которыми столкнулся.
Media 3
Android поставляется с MediaPlayer.
Google рекомендует использовать их опенсорсную библиотеку ExoPlayer.
ExoPlayer V1 была выпущена в 2017.
Затем её сменила не имеющая обратной совместимости ExoPlayer V2, последняя версия которой вышла в июле 2024.
А теперь и её заменили media3, также без обратной совместимости.
Скрипт перехода, который предоставили в Google, далеко не полноценный.
Пуще того, media3 не следует принципам семантического версионирования — обновление младших версий вело к критическим изменениям API.
Библиотека Google Auth
В библиотеке Google Auth был обнаружен баг, плюс в течение нескольких месяцев для API 26 и старше не работала авторизация.
java.lang.NoSuchMethodError: No virtual method getAndSetObject(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;
in class Lsun/misc/Unsafe; or its super classes
(declaration of 'sun.misc.Unsafe' appears in /system/framework/core-libart.jar)
E at com.google.common.util.concurrent.AbstractFuture$UnsafeAtomicHelper.gasWaiters(AbstractFuture.java:1394)
E at com.google.common.util.concurrent.AbstractFuture.releaseWaiters(AbstractFuture.java:1110)
E at com.google.common.util.concurrent.AbstractFuture.complete(AbstractFuture.java:1000)
E at com.google.common.util.concurrent.AbstractFuture.set(AbstractFuture.java:783)
E at com.google.auth.oauth2.OAuth2Credentials$RefreshTask.access$400(OAuth2Credentials.java:600)
E at com.google.auth.oauth2.OAuth2Credentials$RefreshTask$1.onSuccess(OAuth2Credentials.java:617)
...
Прекращение поддержки старых версий Android
Google Ads library v24 перестала поддерживать Android API 21. Согласно официальной статистике Google, этот API использует около 0,1% (~4 миллиона) пользователей. Никаких разумных обоснований своему решению компания не привела.
Обновление ради обновления
На смену Material 2 пришёл Material 3. При этом никакого отчётливого руководства по переходу представлено не было. Почему? Для меня это загадка, которую я так и не смог разгадать. Вот какой толк от того, что основная часть документации теперь ссылается на Jetpack Compose, использовать который я не могу!?
Так что на ближайшее будущее кодовая база Java обречена использовать Material 2.
Руководства по UI-дизайну для Android развиваются непредсказуемо
Нижняя панель навигации, характерная для приложений iOS, поначалу многими воспринималась в штыки, но в итоге стала стандартной фичей в Material design.
Кнопки «вверх» и «назад» раньше могли вызывать расходящиеся действия, а теперь работают одинаково. Узнал я об этом лишь год назад, когда написал по этой теме пост на Reddit.
Некоторые могут решить, что достаточно просто использовать компоненты Material Design. Но переход с одной версии Material Design на другую тоже не так прост. И только вы перейдёте с Material 1 на Material 2, как Google уже выпускает Material 3, оставив прежние версии не у дел.
Google вносит в платформу Android критические изменения
Релиз каждой старшей версии Android несёт в себе критические изменения, создающие для разработчиков серьёзные хлопоты.
Раньше функция toast (всплывающие уведомления) работал в любом режиме приложения, а теперь, начиная с API 31, работает, только если оно находится на переднем плане. А как понять, находится ли твоё приложение на переднем плане? Нужно использовать ActivityLifecycleCallbacks и написать кучу кода, и даже в этом случае есть непонятки с onStart и onResume.
Раньше для показа уведомлений никакие разрешения были не нужны, но с выходом API 33 они стали требовать POST_NOTIFICATIONS.
Разрешения на хранение тоже либо присутствовали все, либо их не было. Теперь же, начиная с API 33, их можно тонко настраивать на уровне аудио, видео и изображений.
Ограничения фонового выполнения кода в каждом релизе постепенно корректируется.
Медиа-уведомления в API 33 заменили на обратно несовместимые. В этом длинном топике можно почитать, какую боль это создало для многих разработчиков.
Важнейшие сторонние библиотеки перестали поддерживаться
Несколько популярных сторонних библиотек были признаны устаревшими или перестали обслуживаться.
Picasso
Picasso была отличным решением для загрузки изображений, но теперь оставлена в прошлом. Её сменила coil, но обновиться на неё не так-то просто.
Glide
Glide является альтернативой Picasso, и её последняя версия была выпущена в сентябре 2023 года.
OkHttp
OkHttp, которую даже Android использует внутренне для реализации HttpURLConnection
, не получала стабильного релиза с октября 2023 года. Последней стабильной версией была 4.12.0, и даже последняя альфа вышла в апреле 2024.
OkHttp 4.12.0 не поддерживает Happy Eyeballs, что создаёт серьёзные проблемы в сетях IPv6.
EventBus
Библиотека EventBus де-факто отвечала в Android за обработку передачи событий. Сейчас её обслуживание прекращено.
RateThisApp
RateThisApp отлично справлялась с получением рейтингов приложений, но в итоге была заброшена.
И я не виню мейнтейнеров. Если вы используете опенсорсную библиотеку, то должны быть готовы к тому, что её поддержка может прекратиться. Я лишь указываю, что некоторые из шаблонных решений, которые зачастую необходимы при разработке под Android, внезапно уходят в небытие.
Две схемы версионирования
В Android используется две схемы версионирования: версия Android API для разработчиков и версия Android для маркетинга.
К примеру, Android 11 работает с API 30, Android 12 — с API 31 и 32 (!), Android 13 — это API 33, а Android 14 – API 34. В документации разработчика отсылка может идти к одной схеме или другой, а иной раз к обеим. И вам нужно учитывать все эти сочетания, занимаясь отладкой с помощью GitHub Issues или StackOverflow, что лишь привносит ненужный дискомфорт и путаницу.
Принудительные обновления
В приложении Android есть множество тесно связанных между собой версий разных элементов.
minSdkVersion
иtargetSdkVersion
приложения,Java
sourceCompatibility
иtargetCompatibility
,версии зависимостей,
версия цепочки системы сборки,
версия Gradle,
версия Android Studio.
И вы можете подумать, что все их обновления делаются по желанию, но это не так.
Gradle и Android Studio необходимо обновлять вместе, чтобы сохранить совместимость.
Обновление Java
sourceCompatibility
иtargetCompatibility
требует обновления Gradle (а значит, и Android Studio).Обновление системы сборки Android требует обновления
minSdkVersion
иtargetSdkVersion
, а также обновления Gradle.Кроме того, если вы хотите продолжать использовать старую библиотеку вроде Exoplayer V2, то рано или поздно она утратит совместимость с другими зависимостями, и вам придётся обновляться до media3.
Вот видите — вы буквально вынуждены обновлять почти всё или ничего.
А что, если вы выберете последнее? Что ж, тогда, если minSdkVersion
вашего приложения окажется слишком старой, оно будет исключено из выдачи.
Заключение
В сравнении с бэкенд-разработкой, разработка под Android требует больше усилий по части обслуживания. Поэтому, если вы планируете создать приложение под эту платформу в качестве хобби, учитывайте постоянную необходимость в его обслуживании.
Дополнение
После публикации этой статьи на главной странице Hacker News, я узнал о двух интересных вещах:
Теперь разработчики приложений, опубликованных впервые после 2021 года, должны предоставлять свои закрытые ключи подписей платформе Google Play Store.
Несколько людей предложили мне публиковать приложения на F-Droid. Но проблема в том, что эта платформа не только имеет малый охват, но и не может разруливать проблемы обратной несовместимости с базовой платформой, с заброшенными библиотеками и обратно несовместимыми изменениями в библиотеках Android.
Комментарии (8)
Ilyaden87
20.06.2025 17:59Автор, в сфере информационных технологий, сейчас, как правило все развивается стремительными темпами. Не только андроид, но ещё и веб, в преимуществе бэкэнд (Kotlin, Spring)
Конечно код не всегда обратно совместим, но с другой стороны если ты уже начал переходить на более новую версию чего либо - то переходить нужно полностью, рефакторив старый код. Критиковать платформу за это немного бессмысленно, так как у других платформ и зависимостей есть аналогичные проблемы. Проще говоря, это касается всей айти сферы, то что было актуально год назад, уже может быть неактуально совсем (и проект даже может не собраться)
Javian
20.06.2025 17:59"Энтропия растет". Когда нибудь почти весь написанный человечеством код невозможно будет запустить, кроме той небольшой части на поддержку которого будет хватать человеко-часов.
Prion
20.06.2025 17:59Недавно наткнулся на новость о том, что количество приложений в Google Play Store сократилось
Выводы какие и куда ушли разработчики? В iOS/Swing? Или RuStore может лучше ?
Простому пользователю, что делать? Андроид фигня переходим на Apple?
henox
20.06.2025 17:59Больше всего меня раздражает то, насколько наплевательски гугл поддерживает свои библиотеки, при их обновлении почти всегда что-то ломается. То в минорных обновлениях несовместимы api, то библиотеки конфликтуют между собой. Очень часто бывает так, что библиотека что-то ломает, а гугл месяцами ничего не делает или вообще игнорирует проблему. В качестве примера: 3 года назад в appcompat что-то изменили, и при нажатии на material кнопку стало появляться два ripple, это до сих пор не исправлено. Я готов обновлять библиотеки и переходить на новое api, только перестаньте их постоянно ломать.
maxsmirnov92
20.06.2025 17:59Не сидится Гуглу на жеппе ровно: постоянно нужно вносить какие-то изменения в базовые вещи и фреймворки (закручивание гаек по некоторым направлениям в стиле яблока - другая история, но она тоже имеет место быть), депрекейтить уже нормально работающее. И при этом они всегда клали болт на обратную совместимость. С одной стороны, глядя на какие-то вещи, разрабы из Mountain View в своей солнечной Калифорнии не зря получают зп, с другой - лучшее, как известно, враг хорошего.Как уже было сказано, нет варианта обновления "по желанию", и одно тянет за собой другое.А ведь кроме этого есть необходимость ещё и обновлять прочие зависимости в проекте, а от каких-то вынужденно отказываться (например, из числа тех, что описаны в посте) и, разумеется, преодолевая неудобства перекатываться на другие.
Джависты должны были отвалиться ещё лет 5 назад: использование kotlin в контексте написания нового даже не обсуждается, а с поддержкой легаси - да, всё обстоит сложнее (в ряде случаев означает "никак" и подразумевает 2 сценария: забить или переписать весь апп заново в зав-ти от мотивации/бюджета). Всё это укладывается в давно известный неудобный принцип: адаптируйся или умри. Сначала какая-то технология или подход (или даже язык) носят рекомендательный характер, а затем становятся обязаловом. Так же это было и с Компостом для построения UI, для которого сейчас (вернее, справедливости ради, уже минимум года два как) вариант есть только один: освоить на необходимом для твоих задач уровне и использовать. Что подразумевает не просто замену одного вызова на другой, а пересмотр связанных, некогда устоявшихся подходов и архитектуры, т.е. в любом случае выход из зоны комфорта.
Если у тебя есть какие-то наработки или либы, то нужно постоянно прилагать усилия для их поддержания, иначе оно быстро теряет актуальность. В частности, появляется куча лапшекода, чтобы поддерживать особенности разных API.
Сейчас не 2015-ый год, и в этом есть свои плюсы и минусы. Например, задаёшься вопросом: а как древние люди (в частности, я) выживали раньше без корутин?Кроме того, гугол ежегодно проводит чистку аппов в маркете, не соответствующих targetSdk и прочим требованиям. Это означает, что ты всегда должен быть "в тренде" по всем изменениям, которые они вносят в ОС и внезапным "нюансам" (большинство из которых вскрываются при более детальном тестировании - для этого к слову, нужен актуальный девайс или эмулятор, которых у меня не оказывается) из-за них всплывающих, и учитывать их в коде - а новые версии штампуются с завидным постоянством. Как будучи пользователем, который ходит с хиаоми с Android 13 и считает его достаточным для большинства повседневных задач, так и разрабом хочется сказать: "астанавитесь!".
mvuhanov
20.06.2025 17:59Про EventBus я бы сильно не переживал. Если взглянуть под капот, то окажется, что это просто статический god object. А если еще и ваши объекты, которые гоняете по шине, вдруг зависят от Context, то получаем в большем проценте случаев memory leak.
Опасненькая штука-то, хоть в чем-то и удобная. Но она такая была всегда. С рождения. В нативных инструментах платформы есть множество других хороших способов реализовать подобное.
Evolitist
Для большей части указанных в статье случаев достаточно поддерживать своё приложение в актуальном состоянии, т.е. время от времени обновлять зависимости, таргет и всякое такое. Бо́льшая часть проблем с версионированием уже решена; такое чувство, будто автор спрашивал у нейронки с катоффом на 22-23 году.
По части именно обслуживания, серьёзных изменений требует обновление таргета, которое всё ещё должно происходить раз в год. Остальное делается фоном, если разработчики адекватные.
JediPhilosopher
Это не работает для пет-проектов. Вот я сделал пешеходный навигатор Sight Safari, про который тут писал https://habr.com/ru/articles/414433/. Он работает, пользователи какие-то есть. Но и развивать я его не развиваю, так как денег он не приносит.
Иногда, редко-редко, фикшу какие-то критические баги.
И тут бац, меня гугл извещает что начиная с какого-то момента если я не обновлю targetSDK на новую версию то меня больше не пустят в гугл плей.
И начались пляски с бубном, так как глобально я проект давно не обновлял. Апдейт tagetSDK тащит за собой апдейт примерно всего: грейдла, андроид студии. Затем выясняется что куча библиотек больше не работает, ведь в новом андроиде еще подзакрутили гайки и поломали совместимость. У меня например это оказалась библиотека рисования карт. Та что у меня новые андроиды больше не поддерживает, а новая версия - это такой мажорный апдейт, который ломает просто ВСЁ приложение, потому что там теперь все делается иначе, другие методы апи, другой флоу работы с картой. Весь старый код (а у меня там много чего было чтобы рисовать свои собственные маршруты по достопримечательностям, а не кратчайшие пути) у меня сломался и перестал работать.
В итоге плюнул и забил. Больше у приложения видимо не будет обновлений.
При том что веб-версия работает и есть не просит.