Building your first Kivy mobile app

Posted 2026-04-10 on the pythondeck.com blog

Kivy is the easiest way to ship a Python app to Android and iOS. This is a walkthrough of building a tiny note-taking app, packaging it for Android with Buildozer, and the gotchas nobody tells you about.

Project layout

notes/
  main.py
  notes.kv
  buildozer.spec   # generated

main.py

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ListProperty

class Root(BoxLayout):
    notes = ListProperty([])
    def add_note(self, text):
        if text.strip():
            self.notes = self.notes + [text.strip()]
            self.ids.entry.text = ""

class NotesApp(App):
    def build(self):
        return Root()

NotesApp().run()

notes.kv

<Root>:
    orientation: 'vertical'
    padding: 12
    spacing: 8
    TextInput:
        id: entry
        hint_text: 'New note...'
        size_hint_y: None
        height: 48
    Button:
        text: 'Add'
        size_hint_y: None
        height: 48
        on_release: root.add_note(entry.text)
    ScrollView:
        BoxLayout:
            id: list
            orientation: 'vertical'
            size_hint_y: None
            height: self.minimum_height
            spacing: 4
            on_parent: pass

Packaging for Android

Install Buildozer on Linux or WSL: pip install buildozer cython. Run buildozer init, edit buildozer.spec to set title, package.name and requirements = python3,kivy, then buildozer android debug deploy run. The first build downloads the Android SDK/NDK and takes 30+ minutes; subsequent builds are fast.

What trips people up

  • Permissions: declare them in buildozer.spec under android.permissions.
  • File paths: use App.user_data_dir, not relative paths.
  • Touch vs mouse: emulate touch in the desktop preview before testing on a phone.
  • Screen density: design in dp units, not pixels.

« all blog posts Browse tutorials