First the app for the example.
It’s a typical Kivy app, taken from the documentation with a few modifications. It implements a simple calculator.
main.py :
import re
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.core.window import Window
from kivy.core.clipboard import Clipboard
class MainApp(App):
def build(self):
self.operators = ["/", "*", "+", "-"]
self.last_was_operator = None
self.last_button = None
Window.clearcolor = (0.071, 0.071, 0.071, 1)
self.title = 'Calculator'
main_layout = BoxLayout(orientation="vertical", padding=[10, 10, 10, 10], spacing=10)
self.solution = TextInput(foreground_color=[0.267, 0.541, 1, 1], background_color=[0, 0, 0, 1],
border=(0, 0, 0, 0), multiline=False, readonly=True, halign="right", font_size=55)
self.solution.bind(on_double_tap=self.on_double_tap)
main_layout.add_widget(self.solution)
buttons = [["7", "8", "9", "÷"],
["4", "5", "6", "×"],
["1", "2", "3", "−"],
[".", "0", "C", "+"],]
for row in buttons:
h_layout = BoxLayout(spacing=10)
for label in row:
button = Button(text=label, pos_hint={"center_x": 0.5, "center_y": 0.5}, font_size=55,
color=[0.502, 0.847, 1, 1], background_color=[0.38, 0.38, 0.38, 1])
button.bind(on_press=self.on_button_press)
h_layout.add_widget(button)
main_layout.add_widget(h_layout)
equals_button = Button(text="=", pos_hint={"center_x": 0.5, "center_y": 0.5}, font_size=55,
color=[0.502, 0.847, 1, 1], background_color=[0.38, 0.38, 0.38, 1])
equals_button.bind(on_press=self.on_solution)
main_layout.add_widget(equals_button)
return main_layout
def on_double_tap(self, instance):
self.solution.select_all()
Clipboard.copy(self.solution.text)
def on_button_press(self, instance):
current = self.solution.text
button_text = instance.text
if button_text == "C":
self.solution.text = ""
else:
if current and (self.last_was_operator and button_text in self.operators):
return
elif current == "" and button_text in self.operators:
return
else:
new_text = current + button_text
self.solution.text = new_text
self.last_button = button_text
self.last_was_operator = self.last_button in self.operators
def on_solution(self, instance):
text = self.solution.text
if text:
exchange = {"÷": "/", "×": "*", "−": "-", "+": "+"}
for char in exchange.keys():
text = text.replace(char, exchange[char])
evalsafe = re.sub(r'[^0-9./*-+]', '', text)
print(evalsafe)
try:
solution = str(eval(evalsafe))
except:
solution = "ERROR! Press C to clear"
self.solution.text = solution
if __name__ == "__main__":
app = MainApp()
app.run()
You can run it locally by issuing python main.py
To be able to compile to APK you’d need a Linux box running python and a set of software.
But if you develop in another OS, it might be fiddly to run and maintain.
Another option is the one presented here, use a google collab free instance to do the compile job step-by-step.
Here is the notebook for the job:
https://github.com/vluz/PythonKivy2AndroidAPK/blob/e8508756c3503f3048a8ba0ad645697694a7be90/PythonKivy2AndroidAPK.ipynb
Just run the notebook in Google collab or click this link:
https://colab.research.google.com/github/vluz/PythonKivy2AndroidAPK/blob/main/PythonKivy2AndroidAPK.ipynb
The first few cells are to prepare the environment. To run just click the play icon (>) at the start of each cell.
Once you reach the text cell named “Copy your main.py to the folder” please copy your application to the collab workspace.
You access the workspace by clicking the files icon on the menu bar on the left.
If you just want to test this procedure, you can use the example above in a text file called main.py
.
Note: Main app file must be called main.py or build will fail.
Next cell creates the config file for the build. You can edit it by double-clicking the file on the workspace. Edit fields as you see fit.
If you make significant changes it is helpful to download the finished config file from the workspace, for later use on another project.
Continue running the cells till it’s done, Compile might take several minutes to complete depending on app.
In the end, after all cells are run, your APK is in the bin
directory of the workspace, download it as it will be deleted when the workspace despawns.
Hope it helps!
Edit: small modification to make eval a bit more safe.