- PVSM.RU - https://www.pvsm.ru -

Недавно наткнулся на новость о том, что количество приложений в Google Play Store сократилось на 47%.
Я сам энтузиаст разработки под Android и последние 5 лет работал над альтернативой для Google Play Music и Podcast [1] под названием MusicSync [1]. Так что, будучи близким к теме человеком, мне захотелось поделиться своим опытом обслуживания приложений и заодно пояснить, почему меня эта новость нисколько не удивила.
У меня есть несколько сторонних проектов [2], базирующихся на бэкенд-сервере с ограниченным веб-интерфейсом, и их обслуживание требует намного меньше усилий.
Если же говорить о приложении Android, то обслуживать его в качестве хобби-проекта гораздо хлопотнее. Вот некоторые из проблем, с которыми мне приходилось сталкиваться:
Если вы начинаете разработку под Android в 2025, то Kotlin явно станет предпочтительным языком. Но что, если вы обслуживаете хобби-проект, написанный на Java? В этом случае вы столкнётесь с проблемами несовместимости, когда обнаружите, что ваши зависимости переписывают на Kotlin.
Если ваш код зависит от библиотеки, использующей корутины Kotlin или опирающейся на suspend-функции [3], то вам придётся искать обходной путь или переписывать своё приложение на Kotlin.
Функциональность Jetpack Compose, официальной библиотеки Google UI для Android, из Java абсолютно недоступна [4].
Могу представить, что вы начали разработку на Kotlin, затем столкнулись с кучей вопросов на StackOverflow, написанных для аудитории Java, и были вынуждены переводить их в равнозначный код Kotlin.
Компания Google славится своей привычкой вносить в библиотеки Android критические изменения. Ниже я перечислил некоторые библиотеки, которые я использовал в своём приложении, и проблемы, с которыми столкнулся.
Android поставляется с MediaPlayer [5].
Google рекомендует использовать их опенсорсную библиотеку ExoPlayer [6].
ExoPlayer V1 [7] была выпущена в 2017.
Затем её сменила не имеющая обратной совместимости ExoPlayer V2 [8], последняя версия которой вышла в июле 2024.
А теперь и её заменили media3 [9], также без обратной совместимости.
Скрипт перехода [10], который предоставили в Google, далеко не полноценный.
Пуще того, media3 не следует принципам семантического версионирования — обновление младших версий [11] вело к критическим изменениям API.
В библиотеке Google Auth был обнаружен баг, плюс в течение нескольких месяцев [12] для API 26 и старше не работала авторизация [13].
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)
...
Google Ads library v24 перестала поддерживать [14] Android API 21. Согласно официальной статистике Google, этот API использует около 0,1% (~4 миллиона) [15] пользователей. Никаких разумных обоснований своему решению компания не привела.
На смену Material 2 пришёл Material 3. При этом никакого отчётливого руководства по переходу представлено не было. Почему? Для меня это загадка, которую я так и не смог разгадать. Вот какой толк от того, что основная часть документации теперь ссылается на Jetpack Compose, использовать который я не могу!?
Так что на ближайшее будущее кодовая база Java обречена использовать Material 2.
Нижняя панель навигации, характерная для приложений iOS, поначалу многими воспринималась в штыки [16], но в итоге стала стандартной фичей в Material design.
Кнопки «вверх» и «назад» раньше могли вызывать расходящиеся действия [17], а теперь работают одинаково [18]. Узнал я об этом лишь год назад, когда написал по этой теме пост [19] на Reddit.
Некоторые могут решить, что достаточно просто использовать компоненты Material Design. Но переход с одной версии Material Design на другую тоже не так прост. И только вы перейдёте с Material 1 на Material 2, как Google уже выпускает Material 3, оставив прежние версии не у дел.
Релиз каждой старшей версии Android несёт в себе критические изменения, создающие для разработчиков серьёзные хлопоты.
Раньше функция toast (всплывающие уведомления) работал в любом режиме приложения, а теперь, начиная с API 31, работает, только если оно находится на переднем плане [20]. А как понять, находится ли твоё приложение на переднем плане? Нужно использовать ActivityLifecycleCallbacks [21] и написать кучу кода, и даже в этом случае есть непонятки с onStart и onResume [22].
Раньше для показа уведомлений никакие разрешения были не нужны, но с выходом API 33 они стали требовать POST_NOTIFICATIONS [23].
Разрешения на хранение тоже либо присутствовали все, либо их не было. Теперь же, начиная с API 33 [24], их можно тонко настраивать на уровне аудио, видео и изображений.
Ограничения фонового выполнения кода [25] в каждом релизе постепенно корректируется.
Медиа-уведомления в API 33 заменили на обратно несовместимые [24]. В этом длинном топике [26] можно почитать, какую боль это создало для многих разработчиков.
Несколько популярных сторонних библиотек были признаны устаревшими или перестали обслуживаться.
Picasso [27] была отличным решением для загрузки изображений, но теперь оставлена в прошлом [28]. Её сменила coil [29], но обновиться на неё не так-то просто.
Glide [30] является альтернативой Picasso, и её последняя версия была выпущена в сентябре 2023 года.
OkHttp [31], которую даже Android использует внутренне для реализации HttpURLConnection, не получала стабильного релиза с октября 2023 года. Последней стабильной версией была 4.12.0, и даже последняя альфа вышла в апреле 2024.
OkHttp 4.12.0 не поддерживает Happy Eyeballs, что создаёт серьёзные проблемы [32] в сетях IPv6.
Библиотека EventBus [33] де-факто отвечала в Android за обработку передачи событий. Сейчас её обслуживание прекращено.
RateThisApp [34] отлично справлялась с получением рейтингов приложений, но в итоге была заброшена.
И я не виню мейнтейнеров. Если вы используете опенсорсную библиотеку, то должны быть готовы к тому, что её поддержка может прекратиться. Я лишь указываю, что некоторые из шаблонных решений, которые зачастую необходимы при разработке под Android, внезапно уходят в небытие.
В Android используется две схемы версионирования [35]: версия 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 необходимо обновлять вместе, чтобы сохранить совместимость [36].
Обновление Java sourceCompatibility и targetCompatibility требует обновления Gradle (а значит, и Android Studio).
Обновление системы сборки Android требует обновления minSdkVersion и targetSdkVersion, а также обновления Gradle.
Кроме того, если вы хотите продолжать использовать старую библиотеку вроде Exoplayer V2, то рано или поздно она утратит совместимость с другими зависимостями, и вам придётся обновляться до media3.
Вот видите — вы буквально вынуждены обновлять почти всё или ничего.
А что, если вы выберете последнее? Что ж, тогда, если minSdkVersion вашего приложения окажется слишком старой, оно будет исключено из выдачи [37].
В сравнении с бэкенд-разработкой, разработка под Android требует больше усилий по части обслуживания. Поэтому, если вы планируете создать приложение под эту платформу в качестве хобби, учитывайте постоянную необходимость в его обслуживании.
После публикации этой статьи на главной странице Hacker News [38], я узнал о двух интересных вещах:
Теперь разработчики приложений, опубликованных впервые после 2021 года, должны предоставлять свои закрытые ключи подписей платформе Google Play Store.
Несколько людей предложили мне публиковать приложения на F-Droid. Но проблема в том, что эта платформа не только имеет малый охват, но и не может разруливать проблемы обратной несовместимости с базовой платформой, с заброшенными библиотеками и обратно несовместимыми изменениями в библиотеках Android.
Автор: Bright_Translate
Источник [39]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/java/423349
Ссылки в тексте:
[1] Google Play Music и Podcast: https://musicsync.ashishb.net/?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[2] несколько сторонних проектов: https://ashishb.net/programming/how-to-deploy-side-projects-as-web-services-for-free/
[3] suspend-функции: https://coil-kt.github.io/coil/java_compatibility/?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[4] абсолютно недоступна: https://stackoverflow.com/questions/66433437/can-i-write-jetpack-compose-components-in-java?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[5] MediaPlayer: https://developer.android.com/reference/android/media/MediaPlayer?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[6] ExoPlayer: https://github.com/google/ExoPlayer?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[7] ExoPlayer V1: https://github.com/google/ExoPlayer/tree/release-v1?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[8] ExoPlayer V2: https://github.com/google/ExoPlayer/tree/release-v2?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[9] media3: https://www.reddit.com/r/androiddev/comments/1atqkjs/is_media3_migration_worth_it/?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[10] Скрипт перехода: https://github.com/google/ExoPlayer/blob/release-v2/media3-migration.sh?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[11] обновление младших версий: https://github.com/androidx/media/issues/2278?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[12] в течение нескольких месяцев: https://gist.github.com/ashishb/108a095603446fa39eb901b006642af6?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[13] не работала авторизация: https://ashishb.net/programming/end-to-end-testing-mobile-apps/
[14] перестала поддерживать: https://developers.google.com/admob/android/migration#migrate-to-v24?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[15] около 0,1% (~4 миллиона): https://composables.com/android-distribution-chart?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[16] воспринималась в штыки: https://androiduipatterns.com/on-the-bottom-navigation-bar-d07d9b4b5e18?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[17] расходящиеся действия: https://web.archive.org/web/20160317020901/http://developer.android.com/design/patterns/navigation.html#up-vs-back?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[18] одинаково: https://developer.android.com/guide/navigation/principles#:~:text=If%20a%20user%20is%20at,and%20does%20exit%20the%20app?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[19] пост: https://www.reddit.com/r/androiddev/comments/1c90gft/android_navigation_up_vs_back/?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[20] только если оно находится на переднем плане: https://developer.android.com/guide/topics/ui/notifiers/toasts?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[21] ActivityLifecycleCallbacks: https://developer.android.com/reference/android/app/Application.ActivityLifecycleCallbacks?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[22] onStart и onResume: https://steveliles.github.io/is_my_android_app_currently_foreground_or_background.html?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[23] POST_NOTIFICATIONS: https://developer.android.com/training/notify-user/notifications#permissions?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[24] начиная с API 33: https://developer.android.com/about/versions/13/behavior-changes-13?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[25] Ограничения фонового выполнения кода: https://developer.android.com/about/versions/oreo/background?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[26] этом длинном топике: https://github.com/androidx/media/issues/216?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[27] Picasso: https://github.com/square/picasso?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[28] оставлена в прошлом: https://www.reddit.com/r/androiddev/comments/1gk6bd9/picasso_is_formally_deprecated/?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[29] coil: https://github.com/coil-kt/coil?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[30] Glide: https://github.com/bumptech/glide?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[31] OkHttp: https://github.com/square/okhttp?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[32] серьёзные проблемы: https://github.com/square/okhttp/issues/506?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[33] EventBus: https://github.com/greenrobot/EventBus?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[34] RateThisApp: https://github.com/kobakei/Android-RateThisApp/?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[35] схемы версионирования: https://developer.android.com/tools/releases/platforms?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[36] совместимость: https://developer.android.com/studio/releases#android_gradle_plugin_and_android_studio_compatibility?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[37] исключено из выдачи: https://developer.android.com/google/play/requirements/target-sdk?utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[38] главной странице Hacker News: https://news.ycombinator.com/item?id=44214835&utm_source=https://ashishb.net&utm_medium=referral&utm_campaign=blog
[39] Источник: https://habr.com/ru/companies/ruvds/articles/919434/?utm_source=habrahabr&utm_medium=rss&utm_campaign=919434
Нажмите здесь для печати.