Kivy can build applications for desktop and mobile including Android and iOS. The same code base can be used for both desktop and mobile, depending on what hardware devices you are trying to access.
This guide will walk through the basics of installing Kivy, building simple applications, building and packaging them for desktop and Android.
Alternatives for desktop application programming with Python are PyQt5, Tkinter, and wxPython. Those packages have a more traditional desktop UI but lack the Android and iOS build capabilities the same way Kivy has. Qt technically supports Android but it is not easy to build with PyQt5.
There are a few concepts to understand in mind when building a Kivy application:
- Layouts - Screen layouts are defined in a
.kvtemplate file using a special Kivy language
- Widgets - The UI elements that get packed in to layout elements. Buttons, for example.
- A layout is just another type of widget
To create a Kivy application in Python, there are a few easy steps:
- Create a class that inherits the Kivy main app class
- Define a
build()method in the class that returns a root widget; anything from a single Button (
kivy.uix.button.Button) to a complex GridLayout (
- Create an instance of your class and call the
That is all there is to a Kivy app at a high level.
You will need to install the Python package
kivy at a minimum.
There is also an optional package called
plyer that contains a number
of cross-platform APIs for accessing device features like notifications
and GPS. Another package used for building Android and iOS is named
You have a few options for installing Kivy:
- From source: https://github.com/kivy/kivy
- Download it from the Kivy website
pipto install the packages
pip to install Kivy:
# The core package python -m pip install kivy # For additional cross-platform APIs like notifications, GPS, and vibrator python -m pip install plyer # For Android/iOS building (Linux only) python -m pip install buildozer # You probablyalso need cython for the Android builds python -m pip install cython # Or use your system package like this for Fedora: sudo dnf install python3-Cython
On Fedora, I needed to install
ncurses-compat-libs to resolve the error:
$HOME/.buildozer/android/platform/android-ndk-r17c/toolchains/llvm/prebuilt/linux-x86_64/bin/clang: error while loading shared libraries: libtinfo.so.5: cannot open shared object file: No such file or directory.
# For Fedora might be needed dnf install ncurses-compat-libs
In Ubuntu, others report similar: https://github.com/kivy/buildozer/issues/841
# Ubuntu fixes sudo apt-get install libncurses5-dev libncursesw5-dev sudo apt-get install libtinfo5
In Windows, you may need to install other dependencies. Official instrucations: Installation in Windows
# Other pip packages to install python -m pip install pypiwin32 python -m pip install kivy_deps.glew # One of the backends: python -m pip install kivy_deps.sdl2 python -m pip install kivy.deps.angle # If needed for video python -m pip install kivy.deps.gstreamer
Check installed version
Once Kivy is installed, you can verify it is installed properly and check what version you have installed.
To check what version of Kivy you have, you run
pip list to check
the Kivy package version, or just open your Python interpreter and
import kivy and inspect
>>> import kivy [INFO ] [Kivy ] v1.11.1 [INFO ] [Kivy ] Installed at "/usr/local/lib64/python3.7/site-packages/kivy/__init__.py" [INFO ] [Python ] v3.7.4 (default, Jul 9 2019, 16:32:37) [GCC 9.1.1 20190503 (Red Hat 9.1.1-1)] [INFO ] [Python ] Interpreter at "/usr/bin/python3" >>> kivy.__version__ '1.11.1'
Start a new project
A Kivy application can be as simple as a single
This is an example of a minimal application that loads a window with one widget, a button:
# main.py # Modified from https://kivy.org/doc/stable/guide/basic.html import kivy kivy.require('1.11.1') # Set to your Kivy version from kivy.app import App from kivy.uix.button import Button class MyApp(App): def build(self): return Button(text='This is a button.') MyApp().run()
Run the application by executing the Python file:
Use the Kv language
In the first example we just returned a single root widget, the button.
You can use methods like
.add_widget() to pack in nested widgets,
but it can be tedious to do all the layout building programmatically.
This is why Kivy created the Kv language for defining widget trees. It is similar to YAML but defines the heirarchy of widgets. It is easier to work with visually and creates separation between the view layer and the controller code.
While the Kv language is optional, and you don't have to use it, it is the preferred way to build layouts and worth getting familiar with. Read more about the KV language in the official Kv language guide
You can provide KV templates as separate
.kv files or as hard-coded
strings inside your Python code.
When building a user interface, you first need to understand the layouts. The layouts will allow you to organize the screen. For example, do you want to stack up a list of buttons vertically, or do you want to have a main frame with a top and bottom bar, or do you want a 3x3 grid of buttons?
Read more about layouts. These are some of the common layout types:
Once you have a layout (which you can nest inside other layouts), you can start putting widgets in it. Widgets are things like buttons, text fields, and checkboxes. Read more about widgets in the official Widget Guide.
Here is an example
.kv file that uses a box layout to hold
two buttons. This creates two buttons side-by-side with no text.
While it is valid and demonstrates the simplest case, it's
not very useful.
# example.kv BoxLayout: Button: Button:
Once you have a
.kv file ready, you need to load it in your application.
By default, it tries to map your app class to a
.kv based off of the name.
For example, if your app is named
PracticeApp it will look for a file named
practice.kv. I prefer to be more explicit and use
to load a specific file. Alternatively, if you don't want to use a file at all, you can use
kivy.lang.builder.Builder.load_string() to load a string with the Kv contents.
Here is an example of how to load the simple
example.kv file we created a few lines above.
# main.py import kivy kivy.require('1.11.1') # Set to your Kivy version from kivy.app import App from kivy.lang.builder import Builder class MyApp(App): def build(self): return Builder.load_file('example.kv') MyApp().run()
A button generally needs some text and and a callback function to be useful though.
We can modify the
.kv file to look more like this:
# example.kv BoxLayout: Button: id: btn1 text: "Button 1" on_press: print("%s was pressed" % btn1.text) Button: text: "Button 2" on_press: print(8 * 8)
You can reference other methods from the
on_press and other events.
For example in the Button object, referencing
self would reference
the Button object, and referencing
root would reference the root
widget in the heirarchy (BoxLayout in this case).
A more powerful way to do this would be to create a custom class that inherits the BoxLayout so we can extend its behavior.
We can swap out the
BoxLayout in the
.kv file and replace it with our
# example.kv MyCustomBoxLayout: Button: text: "Press me" on_press: root.custom_callback() Button:
We haven't actually created the
CustomBoxLayout class though.
We need to add one in our
.py file like this:
# main.py import kivy kivy.require('1.11.1') # Set to your Kivy version from kivy.app import App from kivy.lang.builder import Builder from kivy.uix.boxlayout import BoxLayout class MyCustomBoxLayout(BoxLayout): def custom_callback(self): print('Custom callback called.') class MyApp(App): def build(self): return Builder.load_file('example.kv') MyApp().run()
Running the above example would load the
.kv file and hook up the callback specified
.kv file with the method defined in the
Use Plyer to access mobile device hardware
Plyer is a Kivy package that provides an API to hardware devices like accelerometer, screen brightness, camera, compass, and GPS. It also provides access to some utilities like notifications, which work across desktop and mobile. It's a very ambitious library that has some cool features. Refer to the Plyer documentation for the latest information.
You can also find code examples at: https://github.com/kivy/plyer/tree/master/examples
As of September 2019, I found several of the examples did not work on my Android device. The compatibility still seems to be a bit questionable. Be sure to test out of a module works on device.
python -m pip install plyer
Then you can try building some of the Plyer examples.
See the section further down about how to use
buildozer to build an
.apk file for Android.
Build and package
Now that we have looked at installing Kivy and building a simple application, let's look at how to run and package a Kivy application for distribution. We'll look at desktop applications and then Android. I don't cover iOS because I don't have any experience with it, but Kivy does support it.
Build for desktop
You can share your app in a few ways, starting from simplest to most complex packaging:
- As source code - let people download your source, install Python and Kivy, and run your script themselves.
- As a Python package - Package it with distutils and a
setup.pythat users can install with
python setup.py install
- Push the Python package to pypi.org so others can install it with
- Use PyInstaller to package a .exe or Mac/Linux equivalent. This can create a directory with the .exe and supporting files or a standalone .exe (slower to startup). Distribute this as a .zip for others to download and run. Check out my PyInstaller Tutorial to learn more about how to use it.
- Create an system-specific installer package (e.g. MSI installer with InnoSetup for Window, or a
.debpackage for Ubuntu/Debian) that install the package created with PyInstaller. Check out my Debian Package Tutorial to learn how to make a .deb.
If using PyInstaller to package the application, there is a special step needed in order to ensure the SDL and glew DLLs are included in the final package. These notes are taken from the official instructions at: https://kivy.org/doc/stable/guide/packaging-windows.html#pyinstaller-default-hook.
To use PyInstaller to get a properly built package with the right DLLs,
modify the PyInstaller
.spec file to have at the top:
from kivy_deps import sdl2, glew
And in the
coll object, after the last positional argument, add:
*[Tree(p) for p in (sdl2.dep_bins + glew.dep_bins)],
This will allow it to find and include the right dependencies since they are included in the code.
This helps with errors like
unable to get window.
If you want to create an installer, you need to build an installer for each platform. For example, you can use Inno Setup to build Windows installer wizards.
Build for Android
Let's look at the basic steps for building an Android
.apk with a Python Kivy application.
For more in-depth details on building for Android, check out the official documentation pages:
adb tool is crucial to Android tooling. Buildozer has a way
adb. The one special thing to remember when calling
through the buildozer command is that you need to add two dashes (
before passing the actual command for adb.
To verify everything is working, check the adb version.
version command will also output the full path
adb executable that it is using if you want to run it directly yourself.
python -m buildozer -v android adb -- version # adb path will be something like: # $HOME/.buildozer/android/platform/android-sdk/platform-tools/adb
You can also use adb to list devices like this:
python -m buildozer -v android adb -- devices
Configure the buildozer.spec file
buildozer.spec file has all the configuration for
the Android and iOS build parameters.
Generate a template buildozer spec file using
# Generates a `buildozer.spec` file python -m buildozer init
With the generated
buildozer.spec file, edit it to specify things like:
- Project name
- Source directory
- Files to include and exclude
- Required Python packages
- Icon image -
icon.filenamea 512x512 PNG
- Splash loading image -
presplash.filenamea 512x512 PNG
- Change allowed orientations -
orientation = all
- Log level (
log_level = 2)
- Android Permissions
- Android API level
Build the APK file
Once you have your Python Kivy application
buildozer.spec file for your project.
You can build a debug APK that does not require signing
or a release app that is signed and ready for the Google Play Store.
Build the debug APK
To build the debug APK which doesn't require any app signing,
android debug command for
python3 -m buildozer -v android debug
This will generate an APK file in the
bin/ directory with a name like:
Build the release APK
To build the release APK there is more involved than the debug one. You need to first have a keystore with a key ready to sign the app.
See my Java Keytool Tutorial to learn how to generate and manage keystores. Once you have a keystore, come back and the rest will make sense here.
Also refer to the Kivy Wiki: Creating a Release APK.
The main thing Buildozer needs to have is your keystore information. You can set these values as environment variables. You need to provide the keystore path, keystore password, key alias, and key password.
export P4A_RELEASE_KEYSTORE=$HOME/.keystore export P4A_RELEASE_KEYSTORE_PASSWD=s3cr3t export P4A_RELEASE_KEYALIAS_PASSWD=s3cr3t export P4A_RELEASE_KEYALIAS=mykey
Once your keystore environment variables are set, you can run the release build command:
# Requires the buildozer.spec file python3 -m buildozer -v android release
Release app on the Google Play Store
Once you have a signed release APK from the previous step, you can publish it to the Google Play Store. I have a dedicated tutorial about this topic. Check out How to Publish Android Apps to Google Play Store.
Install the app
Install the application to a device (physical or virtual)
android debug deploy. This will install it
to all connected devices.
python -m buildozer -v android debug deploy
You can also use
buildozer to serve the current directory with
an HTTP server. This is useful so any Android device on the network
can open the HTTP URL in a web browser and download the
.apk and install
it on the device without the need to be connected via USB.
# Serve the current HTTP directory on port 8000 python -m buildozer serve # Essentially the same as Python 3's http.server python -m http.server
You'd then visit
http://<your-hostname-or-ip>/ and navigate to the
Run the app
You can build, install, and run the app all in one step with:
python -m buildozer -v android debug deploy run
- The built .apk file is about 13MB.
- The RAM consumption of simple example in debug is about 60MB.
The stats did not change much between release and debug mode.
View debug log
Use logcat to view the device logs
python -m buildozer -v android logcat
If you run with multiple devices attached it won't tail the logs. If you have one device then you will get the stream of log messages. You can build, install, run, and dump logs in a single step. You will get a ton of log messages so it's best to output it to a file like this:
python -m buildozer -v android debug deploy run logcat 2>log.txt
Other common tasks
Now that we have looked at installing Kivy, creating simple applications, and how to package them for distribution, we have all the knowledge needed to create an app.
At this point you should understand how to
get everything installed, create an application from scratch,
creating custom widgets and callbacks with the Kv language,
and how to build the app in to a
.exe for desktop and a
.apk for Android.
All that information should be enough to continue exploring Kivy and building your own applications.
Kivy also includes packages for many things, including:
- canvas drawing
- 3D rendering
To learn more, follow the official Pong game tutorial.
It shows you how to build a Pong game using
canvas widget, and use the built-it
available on widgets to detect collisions like the ball hitting the paddle.
Also check out the Paint app tutorial which shows you how to detect touches and respond by
Ellipse (circle) at the touch location.
After reading this, you should have a good understanding of what Kivy is
and how you can use it. You should understand how to create desktop apps
and mobile apps by building layouts using the
.kv language. Additionally,
you should know how to use the
plyer package to access cross-platform
features and hardware devices.
- Official Kivy documentation
- Kivy Source
- Kv language guide
- Kivy examples
- Paint app tutorial
- Pong game tutorial
- Widget Guide
- Plyer documentation
- Plyer examples
- PyInstaller Tutorial
- Windows packaging
- OSX packaging
- Android packaging
- Android Kivy guide
- Buildozer source
- Inno Setup Installer
- PyQt5 Tutorial
- Python Tkinter Tutorial
- Bitcoin Price Checker
- Live Stream making Bitcoin Price Checker
- Java Keytool Tutorial
- Kivy Wiki: Creating a Release APK
- How to Publish Android Apps to Google Play Store