Skip to content

How to Use

Video Install Guide

Kivy Reloader Showcase: How to develop on Android

Kivy Reloader Showcase: Hot Reload on Windows

Kivy Reloader Showcase: Create Windows EXE with PyInstaller

In this guide you will learn how to setup and use Kivy Reloader for your projects.

If you are on Windows, you need WSL2 to compile for Android.

If you are on Windows, you need WSL2 to compile for Android.

Instructions on setting up WSL2 to target Android are here.

If you want to use Kivy to target Windows only, you can still follow this Kivy Reloader tutorial! You can choose to setup WSL2 targeting Android later.

Project structure

Select the app structure below according to your experience level: beginner, intermediate, or advanced.

If you are a beginner in Kivy, we will show you a complete app made using only one file.

├── main.py

Create a file main.py and paste this code:

main.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import trio
from kivy.lang import Builder

from kivy_reloader.app import App

kv = """
Button:
    text: "Hello World"
"""


class MainApp(App):
    def build(self):
        return Builder.load_string(kv)


app = MainApp()
trio.run(app.async_run, "trio")

How to use Kivy Reloader

In the project folder, type in the terminal kivy-reloader init.

$ kivy-reloader init

This is going to create two files on your project folder: kivy-reloader.toml and buildozer.spec.

Configure kivy-reloader.toml:

The first time you run kivy-reloader init, you will see on the terminal:

kivy-reloader init

This is the kivy-reloader.toml that has been created on your project folder.

kivy-reloader.toml

Every line has an explanation above. The most important constants on this file are:

  1. PHONE_IPS: Put the IP of your phone here. You can find the IP of your Android phone on: Settings > About phone > Status > IP Address.

image

  1. HOT_RELOAD_ON_PHONE: Set it to True to hot reload on your phone when you press Ctrl + S
  2. FULL_RELOAD_FILES: This is a list of file names (relative paths) that will trigger a live reload (your Kivy app will restart) when they change. In this beginner example, we are watching only the main.py file, and when we change it, the app will restart.
  3. WATCHED_FOLDERS_RECURSIVELY: This is a list of folder names (relative paths), in this beginner example it is [] (empty list). This is because we are not watching any folder, we're only watching main.py. Check the Advanced Example to see how to watch folders.
[kivy-reloader]

PHONE_IPS = ["192.168.1.71"] # Replace with your phone IP

HOT_RELOAD_ON_PHONE = true

FULL_RELOAD_FILES = ["main.py"]

WATCHED_FOLDERS_RECURSIVELY = []

The kivy-reloader init also creates a file called buildozer.spec on your project folder. It has the minimal buildozer.spec that you can use to make your app work with Kivy Reloader on Android.

Pay attention to the folder names

Note that the Reloader will only watch for changes on the files inside the folders you specify. For example, if you want that a change in any file inside the folder screens to cause a hot reload, you must specify the folder screens on the WATCHED_FOLDERS_RECURSIVELY list.

Pay attention to the name of the folders that you want the Reloader to watch. It will not work if you don't do it correctly.

  • Create a file called main.py, a file called app.py and a folder called screens.

  • Inside the screens folder, create two files: main_screen.kv and main_screen.py

.
├── main.py
├── app.py
└── screens
    ├── main_screen.kv
    └── main_screen.py

main.py
1
2
3
4
5
6
import trio

from app import MainApp

app = MainApp()
trio.run(app.async_run, "trio")
app.py
1
2
3
4
5
6
from kivy_reloader.app import App
from screens.main_screen import MainScreen

class MainApp(App):
    def build(self):
        return MainScreen()
screens/main_screen.kv
1
2
3
4
5
<MainScreen>:
    BoxLayout:
        orientation: 'vertical'
        Button:
            text: 'Welcome to Kivy Reloader!'
screens/main_screen.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import os

from kivy.uix.screenmanager import Screen

from kivy_reloader.utils import load_kv_path

main_screen_kv = os.path.join("screens", "main_screen.kv")
load_kv_path(main_screen_kv)


class MainScreen(Screen):
    pass

How to use Kivy Reloader

In the project folder, type in the terminal kivy-reloader init.

$ kivy-reloader init

This is going to create two files on your project folder: kivy-reloader.toml and buildozer.spec.

Configure kivy-reloader.toml:

The first time you run kivy-reloader init, you will see on the terminal:

kivy-reloader init

This is the kivy-reloader.toml that has been created on your project folder.

kivy-reloader.toml

Customize the kivy-reloader.toml

Every line has an explanation above. The most important constants on this file are:

  1. PHONE_IPS: Put the IP of your phone here. You can find the IP of your Android phone on: Settings > About phone > Status > IP Address.

image

  1. HOT_RELOAD_ON_PHONE: Set it to True to hot reload on your phone when you press Ctrl + S
  2. FULL_RELOAD_FILES: This is a list of file names (relative paths) that will trigger a live reload (your Kivy app will restart) when they change. In this intermediate example, we want to restart the app when main.py or app.py changes. So, in this example, set this: FULL_RELOAD_FILES = ["main.py", "app.py"]
  3. WATCHED_FOLDERS_RECURSIVELY: This is a list of folder names (relative paths) that will cause a hot reload if any file inside them changes. In this example it is ["screens"]. This means that a change in any file inside the screens folder will trigger a hot reload.

This is the final kivy-reloader.toml that you will use in this example:

[kivy-reloader]

PHONE_IPS = ["192.168.1.100"] # Replace with your phone IP

HOT_RELOAD_ON_PHONE = true

FULL_RELOAD_FILES = ["main.py", "app.py"]

WATCHED_FOLDERS_RECURSIVELY = ["screens"]

The kivy-reloader init also creates a file called buildozer.spec on your project folder. It has the minimal buildozer.spec that you can use to make your app work with Kivy Reloader on Android.

Pay attention to the folder names

Note that the Reloader will only watch for changes on the files inside the folders you specify. For example, if you want that a change in any file inside the folder screens to cause a hot reload, you must specify the folder screens on the WATCHED_FOLDERS_RECURSIVELY list.

Pay attention to the name of the folders that you want the Reloader to watch. It will not work if you don't do it correctly.

This is the recommended way of structuring your app.

  • Create a file called main.py and a folder called beautifulapp.

  • Inside the beautifulapp folder, create a file called __init__.py.

  • Inside the beautifulapp folder, create a folder called screens.

  • Inside the screens folder, create two files: main_screen.kv and main_screen.py

.
├── beautifulapp
│   ├── __init__.py
│   └── screens
│       ├── main_screen.kv
│       └── main_screen.py
├── main.py

main.py
1
2
3
4
5
6
import trio

from beautifulapp import MainApp

app = MainApp()
trio.run(app.async_run, "trio")
beautifulapp/__init__.py
1
2
3
4
5
6
7
from beautifulapp.screens.main_screen import MainScreen
from kivy_reloader.app import App


class MainApp(App):
    def build(self):
        return MainScreen()
beautifulapp/screens/main_screen.kv
1
2
3
4
5
<MainScreen>:
    BoxLayout:
        orientation: 'vertical'
        Button:
            text: 'Welcome to Kivy Reloader!'
beautifulapp/screens/main_screen.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import os

from kivy.uix.screenmanager import Screen

from kivy_reloader.utils import load_kv_path

main_screen_kv = os.path.join("beautifulapp", "screens", "main_screen.kv")
load_kv_path(main_screen_kv)


class MainScreen(Screen):
    pass

How to use Kivy Reloader

In the project folder, type in the terminal kivy-reloader init.

$ kivy-reloader init

This is going to create two files on your project folder: kivy-reloader.toml and buildozer.spec.

Configure kivy-reloader.toml:

The first time you run kivy-reloader init, you will see on the terminal:

kivy-reloader init

This is the kivy-reloader.toml that has been created on your project folder.

kivy-reloader.toml

Customize the kivy-reloader.toml

Every line has an explanation above. The most important constants on this file are:

  1. PHONE_IPS: Put the IP of your phone here. You can find the IP of your Android phone on: Settings > About phone > Status > IP Address.

image

  1. HOT_RELOAD_ON_PHONE: Set it to True to hot reload on your phone when you press Ctrl + S
  2. FULL_RELOAD_FILES: This is a list of file names (relative paths) that will trigger a live reload (your Kivy app will restart) when they change. In this advanced example, we want to restart the app when main.py or beautifulapp/__init__.py changes. So, in this example, set this: FULL_RELOAD_FILES = ["main.py", "beautifulapp/__init__.py"]
  3. WATCHED_FOLDERS_RECURSIVELY: This is a list of folder names (relative paths) that will cause a hot reload if any file inside them changes. In this example it is ["beautifulapp"]. This means that a change in any file inside the beautifulapp folder will trigger a hot reload.

This is the final kivy-reloader.toml that you will use in this example:

[kivy_reloader]

PHONE_IPS = ["192.168.1.71"] # Replace with your phone IP

HOT_RELOAD_ON_PHONE = false

FULL_RELOAD_FILES = ["main.py", "beautifulapp/__init__.py"]

WATCHED_FOLDERS_RECURSIVELY = ["beautifulapp"]

The kivy-reloader init also creates a file called buildozer.spec on your project folder. It has the minimal buildozer.spec that you can use to make your app work with Kivy Reloader on Android.

Pay attention to the folder names

Note that the Reloader will only watch for changes on the files inside the folders you specify. For example, if you want that a change in any file inside the folder beautifulapp to cause a hot reload, you must specify the folder beautifulapp on the WATCHED_FOLDERS_RECURSIVELY list.

Pay attention to the name of the folders that you want the Reloader to watch. It will not work if you don't do it correctly.

Run your app

Type python main.py on the terminal and your app will start. You can see the logs on the terminal.

python main.py

When you change any file (from the watched folders you specified on the kivy-reloader.toml file), your app will reload.

How to compile and hot reload on Android:

Buildozer does not work on Windows

Kivy Reloader uses Buildozer to compile your app and deploy it on your Android phone. But Buildozer does not work on Windows. If you are on Windows, you need to use WSL2 to compile for Android.

Instructions on setting up WSL2 to target Android are here.

What is Buildozer

Buildozer automates the entire build process, download prerequisites like python-for-android, Android SDK, NDK, etc.

Buildozer manages a file named buildozer.spec in your application directory, describing your application requirements and settings such as title, icon, included modules etc. It will use the specification file to create a package for Android, iOS, and more.

Buildozer can not run on Windows. So this guide must be followed from WSL2.

Step 1: Setup

How to check adb version in Windows and WSL

In Windows Command Prompt, type

$ adb --version

In WSL, type:

$ adb --version

If they are not the same, make sure to find either a Windows or WSL (so Ubuntu version if your WSL is Ubuntu) of adb and downgrade to that.

  • Find your phone's IP address.
Example on finding your Android IP address

Step 1: Go to Settings

Step 2: Go to Connections

Step 3: Go to Wi-Fi

Step 4: Click gear icon

Step 5: Find your phone's IP

Step 2: Connect your phone to the computer using a USB cable.

Step 3: Bridge WSL to your phone.

  • You have 2 options (3 options if your Android is 11+):

PRO: It's very easy. Low setup (just have adb on Windows and on WSL)

CON: Could be laggy depending on wifi setup.

How do I connect WSL adb to my phone through wifi?

The Big Idea...

graph LR
A[WSL ADB] --> B{Wi-Fi};
B{Wi-Fi} --> A[WSL ADB];
B --> C[Android Phone];
C[Android Phone] --> B;

  • Make sure your phone and host Windows are connected to the same Wi-Fi network.

  • On host Windows and WSL, make sure adb is turned off by typing

  • Windows:

    $ adb kill-server
    

  • WSL:

$ adb kill-server

  • Next connect your phone to the computer with the USB Cable.

  • Accept the connection on your phone.

  • On Windows, turn on adb with this command to start a tcpip connection on the 5555 port (you can choose the port number):

$ adb tcpip 5555

  • Check if your device is attached:

$ adb devices

  • Disconnect your Android phone from the host machine USB.

  • Tell the WSL adb which tcpip ip:port to connect to:

$ adb connect phoneip:5555

  • Next check the connection with scrcpy:

$ scrcpy

PRO: No lag as you are connected through USB.

CON: More setup.

How do I connect WSL adb to my phone through wifi?

The Big Idea...

graph LR
A[Android Phone] --> |USB Cable| B[Host Windows adb];
B[Host Windows adb] --> |USB Cable| A[Android Phone];
B --> C[WSL adb];
C[WSL adb] --> B;

  • On host Windows and WSL, make sure adb is turned off by typing

  • Windows:

    $ adb kill-server
    

  • WSL:

$ adb kill-server

  • Get your host machine IP with ipconfig:

$ ipconfig

  • You will need to know which internet is the one providing Wi-Fi.

  • Make sure WSL can ping your host Windows IP:

$ ping 192.168.1.59

  • CTRL+C to stop pinging.

  • If you cannot ping your host machine through WSL, allow WSL through in your wf.msc

  • Connect your phone to computer with USB cable.

  • Accept the connection on your phone.

  • On Windows, start an adb nodaemon server on port 5037 (can be any port number).

$ adb -a -P 5037 nodaemon server

  • On WSL, make sure you can connect to the Windows daemon through that port:

$ adb -P 5037 -H 192.168.1.59 devices

  • You should be able to see your phone.

  • Next, export these variables with the correct numbers.

These are temporary variables that must be exported again on WSL startup.

$ export ANDROID_ADB_SERVER_PORT=5037
$ export ADB_SERVER_SOCKET=tcp:192.168.1.59:5037
$ export ANDROID_ADB_SERVER_ADDRESS=192.168.1.59

  • Test your connection with scrcpy:

$ scrcpy

Reference link

  • On developer options, enable Wireless debugging.

Wireless debugging

  • Click on Pair device with pairing code.

Pair device with pairing code

  • On your WSL, type:

$ adb pair 192.168.1.71:45427 # Replace with your phone IP and port

  • WSL will show "Enter pairing code:". Enter the code shown on your phone. On this example, it is 561605.

  • After pairing, type:

$ adb connect 192.168.1.71:45427 # Replace with your phone IP and port

Step 4: Test scrcpy

  • In the terminal, type kivy-reloader run:

    $ kivy-reloader run
    

    kivy-reloader cli

    What this CLI application does?

    • Compile your app (generate .apk file) and deploy it on your Android phone.
    • Start adb logcat and filter the logs from your app on the terminal.
    • Start scrcpy to mirror your phone screen on your computer.
    • Create a .aab file that will be used to deploy your app on Google Play Store.
    • Restart the adb server for you if needed (to fix issues with adb).

    You can easily control the CLI application using or arrows, and press ENTER ↵ or to select the option you want.

  • Choose the first option and Buildozer will compile the app (create a .apk file) and deploy it on your phone. Once the app is on your phone, run python main.py and the hot reload will be already working.

Just press Ctrl + S in any file inside screens folder or main.py and your app will be updated on computer and phone at the same time. (assuming you have configured the kivy-reloader.toml file correctly).