- Kivy. Сборка пакетов под Android и никакой магии
- Kivy on Android¶
- Package for Android¶
- Debugging your application on the Android platform¶
- Using Android APIs¶
- Plyer¶
- Pyjnius¶
- Android module¶
- Status of the Project and Tested Devices¶
- Create a package for Android¶
- Buildozer¶
- Packaging with python-for-android¶
- Packaging your application for the Kivy Launcher¶
- Installation of Examples¶
- Release on the market¶
- Targeting Android¶
- Разработка игры под Android на Python на базе Kivy. От А до Я: подводные камни и неочевидные решения. Часть 1
- 0. Если вы впервые слышите о Kivy.
- 1. Немного о моей игре
- 2. Kivy тормоз или я что-то делаю не так?
- 3. Сервисы. Автозапуск и перезапуск
- Локализация и мультиязычность
Kivy. Сборка пакетов под Android и никакой магии
Во вчерашней статье Python в Mobile development, в которой речь шла о библиотеке KivyMD (коллекции виджетов в стиле Material Design для использования их в кроссплатформенном фреймворке Kivy), в комментариях меня попросили рассказать о процессе сборки пакета для платформы Android. Для многих этот процесс, к сожалению, был и остается чем-то из ряда магического шаманства и не подъёмным для новичков делом. Что ж, давайте разбираться, так ли на самом деле все сложно и действительно ли я маг и волшебник.
Конечно, мог бы! Итак, вы написали свой код на Python и Kivy. Что нужно для того, чтобы это можно было запустить на Android устройствах? Перейдите в репозиторий KivyMD и вы увидите, что в этой инструкции уже давно прописаны шаги, которые позволят вам собрать APK пакет:
- Загрузите XUbuntu 18.04
Установите Virtual Box на свой компьютер.
Создайте новую виртуальную машину на основе загруженного образа XUbuntu
Запустите виртуальную машину XUbuntu, откройте терминал и выполните нижеследующую команду:
Все! Теперь у вас есть виртуальная машина для сборки APK пакетов для приложений Kivy! Что дальше? Давайте, собственно, займемся сборкой тестового приложения. Создайте в домашнем каталоге вашей виртуальной машины директорию TestKivyMD с пустым файлом main.py:
Далее откройте файл main.py и напишите код нашего тестового приложения, которое будет использовать библиотеку KivyMD:
Сохраните, откройте терминал в директории с файлом main.py и установите библиотеку KivyMD:
После установки можно протестировать наш код:
Результатом работы скрипта будет экран с Toolbar и одной кнопкой «Hello World»:
Дальше нам нужно создать файл спецификации buildozer.spec, который должен располагаться в той же директории, что и файл main.py:
Если вы не закрывали терминал (если терминал был закрыт, откройте его в директории TestKivyMD), введите команду:
Эта команда создаст дефолтный файл спецификации. Откройте его и отредактируйте:
Здесь все понятно поэтому дополнительные комментарии излишни. Почитайте внимательно дефолтную спецификацию, в ней можно указать путь к иконке, пресплеш при загрузке приложения и многое другое. Я оставил лишь то, что нам сейчас нужно для сборки нашего тестового пакета. И, собственно, запускаем процесс сборки командой в терминале:
Можете смело идти на кухню и заваривать кофе, потому что в первый раз процесс загрузки и компиляции библиотек займет очень много времени. Все последующие сборки проходят за 10-20 секунд.
Кофе выпит и самое время заглянуть в терминал:
Вуаля! Наше приложение построено! Самое время закинуть его на смартфон и запустить:
Все работает! И оказывается не все так сложно, как казалось.
Также меня спрашивали:
Ни у Flutter ни у React Native нет преимуществ перед языком разметки Kivy Language, которая позволяет создавать и позиционировать лайоуты и виджеты. Как по мне, то, как строится UI во Flutter — это самое настоящее извращение. Придумать это мог только больной на голову человек. Чтобы не быть голословным, давайте посмотрим на код Flutter и код Kivy одного и того же простейшего приложения… Выглядеть оно будет следующим образом:
Ниже я привожу код из статьи Про Flutter, кратко: Основы:
А вот абсолютно тоже самое, но с использованием Kivy и KivyMD:
По-моему, вывод очевиден и не нуждается в моем комментировании…
Надеюсь, был вам полезен. Оставляю опрос на тему «Удалось ли вам построить приложение для Андроид».
Источник
Kivy on Android¶
You can run Kivy applications on Android, on (more or less) any device with OpenGL ES 2.0 (Android 2.2 minimum). This is standard on modern devices; Google reports the requirement is met by 99.9% of devices.
Kivy APKs are normal Android apps that you can distribute like any other, including on stores like the Play store. They behave properly when paused or restarted, may utilise Android services and have access to most of the normal java API as described below.
Follow the instructions below to learn how to package your app for Android , debug your code on the device , and use Android APIs such as for vibration and reading sensors.
Package for Android¶
The Kivy project provides all the necessary tools to package your app on Android, including building your own standalone APK that may be distributed on a market like the Play store. This is covered fully in the Create a package for Android documentation.
Debugging your application on the Android platform¶
You can view the normal output of your code (stdout, stderr), as well as the normal Kivy logs, through the Android logcat stream. This is accessed through adb, provided by the Android SDK. You may need to enable adb in your device’s developer options, then connect your device to your computer and run:
You’ll see all the logs including your stdout/stderr and Kivy logger.
If you packaged your app with Buildozer, the adb tool may not be in your $PATH and the above command may not work. You can instead run:
to run the version installed by Buildozer, or find the SDK tools at $HOME/.buildozer/android/platform .
You can also run and debug your application using the Kivy Launcher. If you run your application this way, you will find log files inside the “/.kivy/logs” sub-folder within your application folder.
Using Android APIs¶
Although Kivy is a Python framework, the Kivy project maintains tools to easily use the normal java APIs, for everything from vibration to sensors to sending messages through SMS or email.
For new users, we recommend using Plyer . For more advanced access or for APIs not currently wrapped, you can use Pyjnius directly. Kivy also supplies an android module for basic Android functionality.
User contributed Android code and examples are available on the Kivy wiki.
Plyer¶
Plyer is a pythonic, platform-independent API to use features commonly found on various platforms, particularly mobile ones. The idea is that your app can call simply call a Plyer function, such as to present a notification to the user, and Plyer will take care of doing so in the right way regardless of the platform or operating system. Internally, Plyer uses Pyjnius (on Android), Pyobjus (on iOS) and some platform specific APIs on desktop platforms.
For instance, the following code would make your Android device vibrate, or raise a NotImplementedError that you can handle appropriately on other platforms such as desktops that don’t have appropriate hardware::
Plyer’s list of supported APIs is growing quite quickly, you can see the full list in the Plyer README.
Pyjnius¶
Pyjnius is a Python module that lets you access java classes directly from Python, automatically converting arguments to the right type, and letting you easily convert the java results to Python.
Pyjnius can be obtained from github, and has its own documentation.
Here is a simple example showing Pyjnius’ ability to access the normal Android vibration API, the same result of the plyer code above:
This code directly follows the java API functions to call the vibrator, with Pyjnius automatically translating the api to Python code and our calls back to the equivalent java. It is much more verbose and java-like than Plyer’s version, for no benefit in this case, though Plyer does not wrap every API available to Pyjnius.
Pyjnius also has powerful abilities to implement java interfaces, which is important for wrapping some APIs, but these are not documented here — you can see Pyjnius’ own documentation.
Android module¶
Python-for-android includes a python module (actually cython wrapping java) to access a limited set of Android APIs. This has been largely superseded by the more flexible Pyjnius and Plyer as above, but may still occasionally be useful. The available functions are given in the python-for-android documentation.
This includes code for billing/IAP and creating/accessing Android services, which is not yet available in the other tools above.
Status of the Project and Tested Devices¶
These sections previously described the existence of Kivy’s Android build tools, with their limitations and some devices that were known to work.
The Android tools are now quite stable, and should work with practically any device; our minimum requirements are OpenGL ES 2.0 and Android 2.2. These are very common now — Kivy has even been run on an Android smartwatch!
A current technical limitation is that the Android build tools compile only ARM APKs, which will not run on Android devices with x86 processors (these are currently rare). This should be added soon.
As Kivy works fine on most devices, the list of supported phones/tablets has been retired — all Android devices are likely to work if they meet the conditions above.
Источник
Create a package for Android¶
You can create a package for android using the python-for-android project. This page explains how to download and use it directly on your own machine (see Packaging with python-for-android ) or use the Buildozer tool to automate the entire process. You can also see Packaging your application for the Kivy Launcher to run kivy programs without compiling them.
For new users, we recommend using Buildozer as the easiest way to make a full APK. You can also run your Kivy app without a compilation step with the Kivy Launcher app.
Kivy applications can be released on an Android market such as the Play store, with a few extra steps to create a fully signed APK.
The Kivy project includes tools for accessing Android APIs to accomplish vibration, sensor access, texting etc. These, along with information on debugging on the device, are documented at the main Android page .
Buildozer¶
Buildozer is a tool that automates the entire build process. It downloads and sets up all the prequisites for python-for-android, including the android SDK and NDK, then builds an apk that can be automatically pushed to the device.
Buildozer currently works only in Linux, and is a beta release, but it already works well and can significantly simplify the apk build.
This will install buildozer in your system. Afterwards, navigate to your project directory and run:
This creates a buildozer.spec file controlling your build configuration. You should edit it appropriately with your app name etc. You can set variables to control most or all of the parameters passed to python-for-android.
Finally, plug in your android device and run:
to build, push and automatically run the apk on your device.
Buildozer has many available options and tools to help you, the steps above are just the simplest way to build and run your APK. The full documentation is available here. You can also check the Buildozer README at https://github.com/kivy/buildozer.
Packaging with python-for-android¶
You can also package directly with python-for-android, which can give you more control but requires you to manually download parts of the Android toolchain.
Packaging your application for the Kivy Launcher¶
The Kivy launcher is an Android application that runs any Kivy examples stored on your SD Card. To install the Kivy launcher, you must:
Go to the Kivy Launcher page on the Google Play Store
Click on Install
Select your phone… And you’re done!
If you don’t have access to the Google Play Store on your phone/tablet, you can download and install the APK manually from http://kivy.org/#download.
Once the Kivy launcher is installed, you can put your Kivy applications in the Kivy directory in your external storage directory (often available at /sdcard even in devices where this memory is internal), e.g.
should be a directory containing:
The file android.txt must contain:
These options are just a very basic configuration. If you create your own APK using the tools above, you can choose many other settings.
Installation of Examples¶
Kivy comes with many examples, and these can be a great place to start trying the Kivy launcher. You can run them as below:
Run the launcher and select one of the Pictures, Showcase, Touchtracer, Cymunk or other demos…
Release on the market¶
If you have built your own APK with Buildozer or with python-for-android, you can create a release version that may be released on the Play store or other Android markets.
To do this, you must run Buildozer with the release parameter (e.g. buildozer android release ), or if using python-for-android use the —release option to build.py. This creates a release APK in the bin directory, which you must properly sign and zipalign. The procedure for doing this is described in the Android documentation at https://developer.android.com/studio/publish/app-signing.html#signing-manually — all the necessary tools come with the Android SDK.
Targeting Android¶
Kivy is designed to operate identically across platforms and as a result, makes some clear design decisions. It includes its own set of widgets and by default, builds an APK with all the required core dependencies and libraries.
It is possible to target specific Android features, both directly and in a (somewhat) cross-platform way. See the Using Android APIs section of the Kivy on Android documentation for more details.
Источник
Разработка игры под Android на Python на базе Kivy. От А до Я: подводные камни и неочевидные решения. Часть 1
Некоторое время тому назад я решил попробовать написать что-то на Python под Android. Такой странный для многих выбор обусловлен тем, что я люблю Python и люблю Android, а ещё люблю делать необычное (ну хорошо, не самое обычное). В качестве фреймворка был выбран Kivy — фактически, безальтернативный вариант, но он мне очень понравился. Однако, по нему не так уж много информации (нет, документация отличная, но иногда её недостаточно), особенно на русском языке, а некоторые вещи хоть и можно реализовать, но их то ли никто раньше не делал, то ли не счёл нужным поделиться информацией. Ну а я счёл 🙂 И этот пост тому результатом.
Под катом я расскажу обо всех этапах разработки, о том, как развивалась простая идея и как для этого приходилось искать новые возможности, о возникших подводных камнях и багах, о неочевидных решениях и устаревшей документации 🙂 Цель — описать в одном тексте основные пункты, чтобы человеку, решившему написать что-то немного сложнее игры Pong из официального туториала, не приходилось перерывать официальный форум поддержки и StackOverflow и тратить часы на то, что делается за пару минут, если знаешь, как.
0. Если вы впервые слышите о Kivy.
… то всё зависит от того, любите ли вы Python и Android, и интересно ли вам в этом разобраться. Если нет — проще забить 🙂 А если да, то начать нужно с официальной документации, гайдов, и уже упомянутого официального туториала по игре Pong — это даст базовое представление о фреймворке и его возможностях. Я же не буду останавливаться на столь тривиальных вещах (тем более, для понимания базовых принципов туториал отлично подходит) и сразу пойду дальше. Будем считать, что это было вступление 🙂
1. Немного о моей игре
Для начала нужна была идея. Мне хотелось что-то достаточно простое, чтобы оценить возможности фреймворка, но и достаточно интересное и оригинальное, чтобы не программировать ради программирования (это здорово, но когда это не единственная цель — это ещё лучше). Я неплохо проектирую интерфейсы, но не умею рисовать, поэтому игра должна была быть простая графически, или вообще текстовая. И тут так уж сложилось, что у меня есть заброшенный сайт с цитатами, с которого я когда-то начинал свой путь в web-разработке (я о нём даже писал на Хабре много лет назад). Поэтому идея возникла такая: игра-викторина «Угадай цитату». В русскоязычном Google Play ничего подобного не было, а в англоязычном была пара поделок низкого качества с сотней скачиваний.
Почти сразу же стало понятно, что просто так отгадывать цитату за цитатой — скучно. Так появились первые «фишки», которые, в итоге, и определили итоговую игру. В первую очередь это были тематические пакеты (то есть пакеты цитат, объединённые одной темой или автором) и баллы (которые начисляются за отгадывание цитат и прохождение пакетов, и тратятся на подсказки и разблокировку новых тем), а также статистика, достижения и избранное.
Так всё начиналось (кликабельно):
Ну ладно, ладно, больше не буду показывать такой ужас 🙂 Кстати, вот так оно выглядит сейчас (тоже кликабельно, скрины взяты с Google Play):
Первые проблемы начались с первого же экрана…
2. Kivy тормоз или я что-то делаю не так?
Один мой друг любит отвечать на такие вопросы «да» 🙂 На самом деле, некоторые вещи в Kivy действительно работают медленно, например, создание виджетов. Но это не значит, что это дело нельзя оптимизировать. Об этом я и расскажу.
Так как цитаты и темы хранятся в БД, то, само собой, кнопки с пакетами генерируются динамически. И вот тут-то я обнаружил, что происходит это очень медленно: примерно полсекунды на список из 20 кнопок. Возможно, это и не очень много при загрузке приложения, но при переходе на главный экран из других внутренних экранов приложения — непозволительно много. Здесь стоит отметить, что кнопка к тому моменту уже представляла собой, на самом деле, набор из нескольких элементов, визуально составляющих одну кнопку:
Первым моим побуждением было тем или иным образом закешировать их, и, действительно, опыт показал, что если создать все виджеты заранее, и сохранить их как свойство объекта StartScreen, то всё (кроме первой генерации) работает достаточно быстро. Однако же, данные в кнопках нужно периодически обновлять (хотя бы то же количество отгаданных цитат). Да и загрузку новых пакетов я уже тогда планировал. Конечно, не проблема реализовать и это, но я решил не изобретать велосипед и подумать.
Сначала стоило убедиться, что проблема именно в создании виджетов, поэтому я за несколько минут набросал простенькое приложение на два экрана, в каждом из которых генерировался набор строк из лейбла и чекбокса количеством 50 шт. 🙂
Запустил на своём стареньком Moto G (gen3) и получил:
И далее в том же духе. Поиск по этому вопросу ничего не дал, поэтому я обратился к разработчикам. И получил ответ: «Создание виджетов относительно медленное, особенно в зависимости от того, что они содержат. Для создания больших списков лучше использовать RecycleView». Здесь хочу пояснить, почему я вообще описываю этот момент, ведь описание RecycleView есть в документации. Да, действительно, есть, но мало кто способен изучить и запомнить всю документацию перед тем, как начнёт разработку, и найти нужный инструмент бывает непросто, особенно если он нигде не описан в контексте решения конкретной проблемы. Теперь же он описан 🙂
Более чем в 100 раз быстрее. Впечатляет, не правда ли?
В завершение следует упомянуть, что RecycleView — не панацея. Он не подходит, если размер элемента зависит от содержимого (например, Label, размер которого меняется в зависимости от количества текста).
3. Сервисы. Автозапуск и перезапуск
Следующая проблема, с которой я столкнулся, не поддавалась решению так долго, что я уже малодушно подумывал счесть данный фреймворк непригодным и забить 🙂 Проблема была с сервисами (в Android так называется процессы, выполняющиеся в фоновом режиме). Создать сервис не так уж и сложно — немного сбивает с толку устаревшая документация, но и только. Однако, в большинстве случаев, много ли толку от сервиса, который, во-первых, не запускается автоматически при загрузке телефона, а во-вторых, не перезапускается, если «выбросить» приложение свайпом из диспетчера задач? По-моему, нет.
На тот момент по этой теме была всего лишь одна статья в официальной wiki, но она, хоть и называлась «Starting Kivy service on bootup», на самом деле всего лишь рассказывала, как при загрузке телефона запустить приложение, но не его сервис (да, такое тоже бывает полезно, но значительно реже, как по мне). Ту статью я, в итоге, переписал, а здесь расскажу подробности.
Допустим, у нас есть примитивный сервис, который всего-то и делает, что периодически выводит в лог строку (этим мы заранее исключаем баги, которые могут возникать из-за особенностей самого сервиса).
Из приложения мы запускаем его методом основного класса при помощи PyJnius:
Если APK собран правильно, при запуске приложения сервис будет стартовать, но этого недостаточно.
Для начала, попробуем сделать так, чтобы он перезапускался при остановке приложения (например, при снятии его из диспетчера задач). Конечно, можно было бы использовать startForeground, но это уже не совсем фоновое выполнение задачи 🙂 Для него потребуется, как минимум, уведомление — это не всегда подходит. В данном случае идеально подходит флаг START_STICKY, но мы же пишем на Python, что делает задачу не столь тривиальной — по крайней мере, при помощи PyJnius она уже не решается.
Честно говоря, она вообще решается достаточно криво, поскольку я пока не готов становиться одним из разработчиков Python4Android, благодаря которому всё это счастье вообще работает. А изменения нужно вносить именно в код Python4Android. А конкретно, нам нужен файл .buildozer/android/platform/build/dists/guessthequote/src/org/kivy/android/PythonService.java в котором в функции startType() мы меняем флаг START_NOT_STICKY на START_STICKY:
Ура, сервис рестартится. Всё? Конечно, нет 🙂 Потому что он тут же валится с ошибкой:
Проблема в функции onStartCommand(Intent intent, int flags, int startId), поскольку после перезапуска intent у нас null. Что ж, перепишем и её:
Проблема в том, что функция nativeStart() не получает нужных Extras. К сожалению, два из них мне пришлось захардкодить. В итоге выглядит это так:
Перейдём к автозапуску сервиса при запуске телефона. После предыдущей проблемы это будет уже проще. (На самом деле же всё было наоборот — я очень долго не мог понять, что именно нужно добавить, поскольку информации об этом не было вообще нигде, и сами разработчики тоже не знали, как решить данную задачу. И только разобравшись параллельно с вопросом перезапуска, я понял, что нужно сделать.)
Для начала понадобится разрешение RECEIVE_BOOT_COMPLETED — это просто. А затем — BroadcastReceiver, его придётся добавить в AndroidManifest вручную, но это тоже не проблема. Проблема в том, что в нём писать 🙂
Решение для запуска приложения (не сервиса) выглядит так:
Сначала я попытался просто переписать его для сервиса:
Думаю, вам уже понятно, что проблема в тех самых Extras. Мне же тогда об этом было узнать неоткуда. Но не буду тянуть, рабочий код выглядит так:
Локализация и мультиязычность
В целом, для локализации можно использовать gettext, или же поступить ещё проще — создать папку lang, в ней по файлу на каждый язык (например, en.py и ru.py), определить там все слова и фразы в виде переменных/констант, и далее подключить нужный модуль. Примерно так:
Статическая переменная использована для того, чтобы языковые константы было удобно использовать в kv-файле:
Источник