Artean

Создание приложения на андроид на Python: опыт команды разработчиков

Почему Python может быть хорошим выбором для Android-разработки

Python традиционно ассоциируют с веб-разработкой, анализом данных и автоматизацией. Но благодаря таким инструментам, как Kivy, создание приложения на андроид с помощью Python стало технически возможным. Несмотря на то, что Android-разработка по умолчанию ориентирована на Java и Kotlin, в ряде случаев Python даёт ощутимое преимущество на ранних этапах развития продукта.

Речь идёт прежде всего о стартапах и MVP. Когда нужно верифицировать идею с минимальными затратами, Python и фреймворки вроде Kivy позволяют быстро собрать функциональный прототип. Особенно если команда уже умеет работать с этим языком. В таких случаях выигрыш по времени может достигать 30–50% по сравнению с Java/Kotlin: разработка интерфейса быстрее, подключение логики проще, знакомая экосистема библиотек остаётся в арсенале.

Есть и организационные поводы выбрать Python:

  1. бэкэнд уже написан на Django или Flask — проще переиспользовать логику и разработчиков;
  2. на проекте ограничены сроки и бюджет — меньше ресурсов на декомпозицию и синхронизацию фронта и сервера;
  3. в команде нет Android-разработчика, но есть Python-инженеры, готовые адаптироваться.

В таких условиях Python под Android — это прагматичный, если не идеальный, выбор. Из значимых инструментов, работающих в этой связке, выделим:

  1. Kivy — кроссплатформенный фреймворк на Python, основной инструмент для GUI-приложений под Android;
  2. KivyMD — расширение Kivy с компонентами визуального стиля Material Design;
  3. Buildozer — утилита для сборки проекта в APK, использующая p4a (Python for Android);
  4. Chaquo — плагин для Android Studio, позволяющий интегрировать Python-модуль в нативное приложение;
  5. BeeWare — менее зрелый, но перспективный стек для создания нативных приложений на Python.

Разумеется, у подхода есть ограничения. Если вы разрабатываете игру с 3D-графикой, высоконагруженное приложение, требующее сложной работы с потоками, или хотите использовать последние возможности Android (например, Jetpack Compose или ARCore), использовать Python — не лучший путь. На таких проектах буквально каждая миллисекунда важна, и интерпретируемый язык с прослойками теряет конкурентоспособность.

Однако как промежуточный этап, как стартовая позиция для тестирования идеи, или как способ переиспользовать уже написанную логику — Python под Android может быть мощным, стратегически оправданным решением.

Архитектура проекта: как мы организовали разработку Android-приложения на Python

Мы подошли к архитектуре Android-приложения на Python со строгой модульной структурой. Несмотря на отсутствие официальных стандартов для архитектуры в Kivy, мы сознательно внедрили принципы, близкие к MVC и MVVM, чтобы облегчить масштабирование и поддержку.

Основные слои нашего приложения:

  1. View — описан с помощью KV-файлов (специальный язык разметки в Kivy), разграничивает интерфейс от логики;
  2. Model — отдельные Python-модули, инкапсулирующие бизнес-логику и доступ к данным — как локальным, так и удалённым;
  3. Controller/ViewModel — Python-классы, обрабатывающие пользовательские действия и синхронизирующие модель с интерфейсом;

Для хранения данных использовалась библиотека TinyDB — простая, JSON-ориентированная embedded-база, максимально легко интегрируемая в Python-среду. В перспективе мы планировали переключиться на SQLite через адаптеры Plyer или напрямую через Python-библиотеки (напомним, что Android уже содержит нативный SQLite, но доступ к нему через Python всё ещё требует осторожности из-за различий в зависимости от архитектуры устройства).

Взаимодействие с API реализовано через стандартную библиотеку requests, с обёртками для обработки ошибок и timeouts. Одновременно добавили аналитический слой — события действий пользователя фиксировались и передавались на внешний сервер, поддерживая off-line кеширование до восстановления соединения.

Интеграция с Android-специфичными функциями — камера, файловая система, GPS — происходила через Kivy + Plyer. Plyer предоставляет обёртки для различных мобильных API через Python. Например, модуль plyer.camera позволял нам инициировать снимок и загрузить изображение. Однако этот путь не безупречен: для выбора качества фото, разных фронтальных/тыловых камер — потребовалась отдельная наработка на Java-стороне.

Некоторые функции, завязанные на Android SDK напрямую (push-уведомления Firebase, deep links), мы вынесли в Java-модули и подключили через JNI. Для этого Buildozer позволяет добавлять кастомные .aar и Java-классы, которые затем становятся доступными в Python-коде через pyjnius (библиотека для взаимодействия Python и Java-кодом на уровне байткода).

Такой подход — смешанный: максимум логики на Python, но то, что слишком “андроидное”, уходит в Java. Это минимизирует дублирование и позволяет масштабировать команду — Python-разработчики остаются сосредоточены на себе понятной среде, а Android-специалисты включаются точечно.

Практические особенности разработки на Python под Android

Сборка APK на Python — довольно отличающийся процесс по сравнению с Android Studio. Здесь главное — выбор сборщика. Мы тестировали два инструмента:

  1. Buildozer — open-source утилита, формирует полноценный APK из Kivy-приложения. Использует под капотом Python-for-Android (p4a);
  2. Chaquo — плагин для Android Studio, который позволяет добавить Python-модуль в стандартный Android-проект. Хорошо подходит, если нужна гибридная архитектура — часть на Kotlin, часть — на Python.

Buildozer показал себя как более стабильный инструмент, особенно для независимых Python-приложений на базе Kivy. Его конфигурация происходит через файл buildozer.spec, где указываются зависимости (в том числе pip-зависимости), классы доступа (интернет, камера, гироскоп и т.д.), иконки, ориентация экрана, архитектура (arm64-v8a и др.).

Тем не менее, в ходе разработки возникли конкретные проблемы, с которыми мы столкнулись и которые стоит предусмотреть заранее:

  1. Ошибки с разрешениями: Android 11+ требует запроса разрешений во время работы приложения — runtime permissions, а не только в манифесте. Kivy сам по себе этого не поддерживает — мы использовали плагин android.permissions с ручной проверкой через Java.
  2. Несовместимость с AndroidX: часть внешних AAR-библиотек требует AndroidX, чего не предусмотрено в стандартной сборке через Python — приходилось вручную патчить зависимости и явно прописывать правила в gradle.
  3. Отсутствие готового Google Maps: в экосистеме Kivy нет готового виджета для карт Google. Мы использовали OpenStreetMap через Kivy Garden, но с оговорками: кастомизация, работа с маркерами и производительность ощутимо уступают стандартным решениям.

Что касается интерфейса — здесь важную роль сыграла KivyMD. Kivy сам по себе довольно базовый: кнопки, метки, поля — да. Но для приличного UX под Android нужны Material Elements: FAB-кнопки, BottomSheets, навигационные панели. Всё это даёт KivyMD — достойная реализация Material Components.

Однако есть нюансы:

  1. Производительность интерфейса с анимациями — ощущается «плотность» Python-интерпретации. На слабых устройствах иногда заметны подгрузки или фризы;
  2. Некоторые компоненты KivyMD не поддерживают кастомизацию ожидаемую от Android-разработчика — например, Snackbar сложнее интегрировать в сложный макет;
  3. Тестирование UI требует визуальной регрессии — мы применяли автоматические скриншотные библиотеки, чтобы проверять отображение компонент на разных экранах.

Для проверки на разных версиях Android мы собрали парк из четырёх физических устройств (от Android 7 до 13) и использовали эмуляторы AVD, предварительно настраивая им доступ к камере и сети. Автотесты писали на базе unittest + Appium (для UI). Отладка происходила через логгеры, adb и tiki-py-debug сервер прямо внутри сборки.

Совет от команды: всегда держите два Buildozer-образа — стабильно собранный под arm64, и экспериментальный. Сыграло десятки раз: когда обновление KivyMD ломало совместимость, мы быстро возвращались к стабильной сборке.

Сравнение с Java/Kotlin: оправдана ли игра

Чтобы оценить рентабельность создания приложения на андроид на Python, мы провели тест: реализовали одно и то же приложение — простой таск-трекер — двумя способами. Первый — на традиционном стеке Kotlin + Jetpack, второй — на KivyMD + Python. Условия: один экран со списком задач, добавление/удаление, хранение данных локально, смена статуса.

Результаты:

  1. Время разработки: команда из Python-разработчиков реализовала версию на Kivy за 2,5 рабочих дня. Kotlin-вариант с нуля написали за 4 дня, несмотря на готовые шаблоны из Android Studio;
  2. Кодовая база: на Python — 420 строк, на Kotlin — более 900 за счёт декларативной UI-разметки, ViewModels и работы с Room;
  3. Производительность: на низкоуровневых устройствах Kotlin-версия работает заметно быстрее: быстрее рендерит списки, отзывчивость UI выше;
  4. Визуальные элементы: Kotlin-приложение сразу “вписывается” в Android-экосистему, лучше адаптируется под тёмную тему, gestures, и локализацию. Kivy-приложение требовало дополнительной настройки для схожей адаптивности.

Вывод: если критичны производительность, нативное поведение UI и глубокая интеграция — Kotlin несомненно выигрывает. Но если цель — быстро получить работающий функционал, который не зависит от Android SDK на 100%, и в команде уже есть Python-разработчики — экономические и организационные выгоды Python-версии очевидны.

Интересный момент: впоследствии мы «переписали» Python-версию на Kotlin и смогли перенести около 75% бизнес-логики практически без изменений. Благодаря архитектурному разделению и использованию REST API, основной функционал остался за пределами GUI. Это подтверждает, что использование Python на первом этапе не блокирует масштабирование — наоборот, позволяет сформулировать чёткие требования для будущей нативной версии.

Как мы подготавливали приложение к публикации в Google Play

Сам процесс подготовки APK на Python для Play Market имеет свои сложности. После завершения разработки мы столкнулись с несколькими проблемами, не типичными для Kotlin/Java-сборок.

Первая задача — подпись APK-файла. Buildozer позволяет сразу задавать keystore и подпись через конфигурацию, но практика показывает: безопаснее подписывать APK вручную при помощи jarsigner и zipalign от Android SDK. Это даёт больше контроля, особенно при пересборке релизов.

Вторая задача — оптимизация сборки. Приложения, собранные через Buildozer, по умолчанию весят больше. Один из релизов достиг 37 МБ на файл с минимальной функциональностью. Мы провели:

  1. чистку неиспользуемых pip-зависимостей;
  2. удаление неиспользуемых модулей KivyMD через форк библиотеки;
  3. включение only arm64-v8a архитектуры (удалили 32-битные компоненты, чтобы не дублировать бинарники);
  4. проверку ресурсов и manual zip-сжатие.

Ключевой вызов возник с требованиями Google: начиная с августа 2021 года, Play Store больше не принимает 32-битные APK. Buildozer по умолчанию собирает оба варианта (armeabi-v7a и arm64-v8a), что создавало конфликты при разборе App Bundle. Мы решили это через явное указание платформы в buildozer.spec:

android.arch = arm64-v8a

Также важно учитывать требования безопасности: если библиотека работает с файлами, фотографиями, контактами — Play Console требует манифеста использования. Python-приложения не всегда корректно отображают разрешения при разборе APK — приходилось вручную указывать цели использования в privacy policy и флагах конфигурации.

Особенности подготовки Python-приложения для публикации:

  1. Google Play проверяет все встроенные библиотеки на наличие уязвимостей — pip-пакеты, в том числе неоптимизированные, могут “засветиться”;
  2. Подписанные APK нужно проверять на совместимость с targetSdk — Buildozer по умолчанию может собрать под API 28, хотя сейчас требуется 33 и выше;
  3. Сканеры Play Store не всегда корректно интерпретируют Python-часть, особенно если используются миксованные библиотеки Java + Python. Возможны ложные флаги в безопасности;

Рекомендация: провести финальную проверку через APK Analyzer из Android Studio. Это помогает выявить избыточные пакеты, убедиться в подписи и целостности сборки.

Совет от команды: для первого релиза лучше избегать использования push-уведомлений и deep linking — они наиболее чувствительны к различиям платформ и плохо отлаживаются в смеси Python и Java.

Что можно и чего нельзя сделать на Python в Android-приложениях сейчас

Несмотря на гибкость стеков вроде Kivy, не всё в Android доступно в Python по умолчанию. Мы составили внутрикомандный чеклист, который помогал быстро оценивать: реализуемо ли то или иное требование без нативного кода.

Что можно сделать на Python под Android с помощью Kivy и дополнительных библиотек:

  1. Работа с офлайн/онлайн хранением данных — TinyDB, SQLite, JSON;
  2. Авторизация через API и формирование защищённых токенов (OAuth2 через requests);
  3. Интеграция с GPS и геолокацией с помощью Plyer;
  4. Работа с камерой — включает съёмку и загрузку, но не глубокую настройку;
  5. Push-уведомления через дополнительный Java-модуль (например, FirebaseMessagingService);
  6. Simple media player с использованием plyer.audio или mplayer при кастомизации сборки.

Что потребует слоя на Java или нереализм без костылей:

  1. Нотификации сложного типа с actions, каналами и планировщиками;
  2. Biometric authentication через AndroidX Biometric / API 28+;
  3. Интеграция с Google API: Maps, Sign-In, Cloud Messaging;
  4. Ответ на звонки, активное использование контактов, SMS, Bluetooth сопряжение;
  5. Widget на домашний экран Android или интеграция с quick-settings tiles.

Факты на практике: нам удалось реализовать запись геометки при фото, синхронизацию задач с сервером через OAuth2 и поддержание сессии, пустые уведомления с cron-таймером. Но был провал при попытке реализации кастомного MapView поверх OpenGL без значительных прослоек на Java. Производительность не выдерживала каких-либо длинных маршрутов — даже на Pixel 6 отрисовка карты “подвисала”.

Рекомендация: до начала спринта определите список ожидаемых функций и соотнесите его с возможностями Kivy и Plyer. Реализация «простого модуля карт» может обернуться неделями нативного кода, а push-уведомления — конфликтами версии Firebase SDK.