Configure your Android app¶
Your Android configuration lives in the [tool.kivy.android] overlay of your
pyproject.toml. This page covers the settings you change most often. For every
key, see the Android overlay reference.
Before you begin¶
- Install kivyforge and the Android toolchain: a JDK in the supported range, the Android SDK, and the Android NDK (Native Development Kit).
- Have a project with
[project]section (kivyforge initadds[tool.kivy], below). See Project configuration.
Start from a template
Run kivyforge init -p android in the folder that holds your
pyproject.toml. It adds [tool.kivy] and a [tool.kivy.android] overlay with
comments and TODO markers on the values you need to change, so you edit a
working file instead of typing the Android overlay by hand. To
regenerate an overlay that already exists, add --force. See
Seed overlays with init.
Start from a minimal overlay¶
This overlay is the one the hello-android example uses:
[tool.kivy.android]
schema_version = 1
package = "org.kivyforge.helloandroid"
min_sdk = 24
target_sdk = 35
kivy_generation = 2
abis = ["arm64_v8a", "x86_64"]
extra_index_urls = ["https://elliotgarbus.github.io/kivy-mobile-wheels/simple/"]
exclude = ["kivy-garden", "docutils", "pygments"]
[tool.kivy.android.python]
version = "3.14.6"
[tool.kivy.android.permissions]
uses = ["INTERNET"]
schema_version, package, and [tool.kivy.android.python].version are
required. The other keys shown have defaults, listed in the reference.
Key settings¶
package- The applicationId, in reverse-DNS form (
org.example.myapp). It is your app's identity on the device and on Google Play, and you cannot change it for a published app. version_code- The integer Google Play uses to order uploads. Set
version_code = "auto"to derive it from[project].version, so you bump only one version. min_sdkandtarget_sdk- The minimum and target Android API levels.
min_sdkcannot be lower than24. Keeptarget_sdkat Google Play's current requirement; see Supported Android versions. kivy_generation-
2for Kivy 2.3.1 on SDL2,3for Kivy 3.0 on SDL3. It selects the matching SDL bootstrap and must match the Kivy version in your dependencies.It does not choose the Kivy version
kivy_generationis not an input to dependency resolution. The Kivy that gets locked comes only from[project].dependencies. Withkivy_generation = 3and a plainkivyrequirement,kivyforge lockstill pins 2.3.1, because pip skips pre-releases. Require Kivy 3.0 yourself, for example"kivy>=3.0.0.dev0,<4", with an index that hosts it. That range moves to the newest snapshot on every re-lock. To stay on one snapshot, pin it exactly.kivyforge lockandkivyforge doctorboth warn when the two disagree.Generation 2 keeps clear of the system bars
Android 15 and later draw an app edge to edge, under the status bar and the navigation bar. Kivy 2.3.1 can't report a safe area, so with
kivy_generation = 2the app's window is kept clear of the bars and the notch, with black behind the bars. This applies on API 30 and higher. Withkivy_generation = 3the app draws edge to edge and pads its own layout by the safe area. abis- The ABIs (application binary interfaces) to build. Physical phones use
arm64_v8a. Most emulators on an x86_64 computer usex86_64. Keep both to cover development and distribution. extra_index_urls- Where to find the Android builds of Kivy and pyjnius, which are not on PyPI yet.
exclude- Dependencies that Kivy declares but an Android app does not use. Pruning them keeps the lock and the app smaller.
fullscreen- Set
fullscreen = trueto hide the status bar and the navigation bar while your app runs. A swipe in from the edge shows them for a few seconds. It defaults tofalse. buildozer's default is the reverse, so set it explicitly when you migrate an app that relied on that default. Fullscreen does not remove the notch, so keep padding your layout by the safe area. Withkivy_generation = 2, kivyforge keeps the window clear of the notch for you.
Add an icon and a splash screen¶
Point [tool.kivy.android.icons] at a 1024x1024 PNG. kivyforge generates the
adaptive icon set from it.
[tool.kivy.android.icons]
source = "assets/icon.png"
[tool.kivy.android.splash]
source = "assets/splash.png"
background = "#1e1e2e"
Without an icon source, kivyforge generates a plain default icon. Without a splash source, it generates no splash screen.
Add Android resources¶
To ship your own Android resources, such as vector drawables, a notification
icon, density-specific images, values/ files or xml/ configuration, keep
them in a folder laid out like an Android res folder and stage it with
include_files:
android_res/
├── drawable/
│ └── ic_notification.xml
├── drawable-night/
│ └── banner.xml
├── drawable-xxhdpi/
│ └── banner.png
├── values/
│ └── colors.xml
└── xml/
└── network_security_config.xml
[[tool.kivy.android.include_files]]
dest = "app/src/main/res"
sources = ["android_res"]
A directory source copies its contents, subfolders included, so
android_res/drawable-night/banner.xml ends up at res/drawable-night/banner.xml.
Qualifiers such as -night, -v26, -xxhdpi or -land are ordinary Android
folder names; kivyforge copies them as they are and AAPT, Android's resource
compiler, interprets them. Combined qualifiers must follow
Android's order,
for example drawable-night-xxhdpi.
kivyforge lock records a hash for every file, so after adding, editing or
removing one, run kivyforge lock -p android again. A file you remove from the
folder is also removed from the generated project on the next build.
A service's notification icon is a resource name, looked up as a drawable and
then as a mipmap, so drawable/ic_notification.xml above is
icon = "ic_notification" in the service's
notification table.
Replacing a file kivyforge generates¶
kivyforge writes some resources itself: values/strings.xml (the app name),
values/styles.xml (the app theme), the launcher icon under mipmap-*, and the
splash screen when one is configured. A file of yours at the same path replaces
kivyforge's, and the build says so with KF-ANDROID-INCLUDE-OVERRIDE.
The generated manifest uses the string app_name and the style
Theme.Kivyforge, so a replacement strings.xml or styles.xml must still
define them, or the build stops and says which one is missing. Replacing
styles.xml also drops what kivyforge put in that theme for fullscreen and
the splash screen. To add values without replacing anything, use files with
other names, such as colors.xml or themes.xml. To change only the theme's
parent, set [tool.kivy.android].base_theme.
SVG files
Android does not accept SVG files in res/. Convert them to vector
drawable XML first, for example with Android Studio's Vector Asset tool.
Declare permissions¶
List the permissions your app needs. For permissions that imply hardware, such
as CAMERA, kivyforge also adds a non-required <uses-feature> entry so Google
Play does not hide your app from devices without that hardware:
[tool.kivy.android.permissions]
uses = ["INTERNET", "CAMERA"]
Verify¶
Any change to pyproject.toml makes the lock stale, so re-lock, then build a
debug APK (Android Package):
kivyforge lock -p android
kivyforge build -p android --debug --abi x86_64
kivyforge rejects an invalid value with a message that names the key. It ignores keys it does not recognize, so a misspelled key has no effect instead of failing.