How ApkPy generates an Android app¶
ApkPy is a source compiler, not a Python runtime for Android. It reads the supported Python model, builds an internal application tree and emits a normal Android project.
The compilation pipeline¶
writehere.py
│
├─ 1. Python AST parsing
├─ 2. screen, component and callback collection
├─ 3. CSS + Theme cascade resolution
├─ 4. feature detection and permission planning
├─ 5. Java, XML and resource emission
└─ 6. Gradle project packaging or APK compilation
1. Parse supported Python¶
The compiler uses Python's abstract syntax tree. It does not execute arbitrary
Python and then attempt to copy a desktop interface. Calls such as Screen,
button, db.query and audio.play_background have explicit Android
generation rules.
home = Screen(id="home")
def save():
value = name_input.get_value()
if value == "":
toast("Enter a name")
return
storage.set("name", value)
button("Save", command=save, screen=home)
The callback becomes a Java method. Supported conditions, loops, conversions and component operations are translated to their Java equivalents.
2. Build the screen tree¶
Each Screen becomes an Activity. Components attached with screen= become
root children; components attached with parent= are nested in the matching
container, card or layout.
home = Screen(id="home", scroll=True)
summary = card(id="summary", variant="outlined", screen=home)
label("This month", variant="overline", parent=summary)
label("€ 1,240", variant="title", parent=summary)
For a scrollable screen, Android receives a NestedScrollView and one content
tree. Rich lists inside that screen use a non-nested representation so Android
does not fight over touch scrolling.
3. Resolve Theme and CSS¶
Style resolution follows a predictable cascade:
button { border-radius: var(--radius); }
button:outlined { border-color: var(--primary); }
save_button { background-color: #22D3EE; }
The ID rule wins. The generated project receives colors, drawable shapes,
dimensions and a Material-compatible Theme.App rather than a CSS engine at
runtime.
4. Detect features before emitting helpers¶
ApkPy scans what the app actually uses:
| Source feature | Generated Android addition |
|---|---|
https.* or remote image |
INTERNET permission and background networking |
audio.play_background |
foreground media service, MediaSession and notification |
auth.login |
OAuth callback Activity and deep-link manifest entry |
| advanced flex/grid | ApkpyLayout ViewGroup |
| image cache/effects | bounded cache, image workers and bitmap helpers |
skeleton |
one shared animation helper for the Activity |
A project that does not call one of these APIs does not receive its helper. This keeps the ordinary path understandable and reduces unused code.
Representative generated output¶
Given this declaration:
the layout contains a Material button with a generated style/drawable, while the Activity locates the view and attaches the callback. Simplified:
<com.google.android.material.button.MaterialButton
android:id="@+id/continue_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="48dp"
android:text="Continue" />
MaterialButton continue_button = findViewById(R.id.continue_button);
continue_button.setOnClickListener(view -> {
pythonCallback_continue_flow();
});
The snippets above are shortened for explanation. The exact output also contains resolved margins, colors, accessibility text, drawable references and any imports required by the complete screen.
Previewer parity¶
The Hot Previewer interprets the same screen tree and callbacks using desktop widgets. It is deliberately a development feedback loop, not an Android emulator.
| Behavior | Previewer | Android |
|---|---|---|
| component state | in-memory desktop objects | native View state |
| key/value storage | encrypted local file | encrypted SharedPreferences |
| SQLite | Python sqlite3 | Android SQLiteDatabase |
| HTTP | background Python request | background HttpURLConnection |
| media | desktop media backend | foreground Android media service |
| date/time picker | desktop simulation | native Android dialog |
Use the Previewer to iterate. Use an emulator or real device to validate permissions, services, manufacturer behavior and the final platform rendering.
What remains in your control¶
writehere.pyremains the source of truth;apkpy.tomlcontrols name, package ID, version and icon;- Android Studio can inspect the generated project;
- signing keys remain local and must be backed up;
- server-side secrets and privileged authorization stay on your backend.
Continue with Components and layouts, Data, network and security, or the public API reference.