-
Notifications
You must be signed in to change notification settings - Fork 0
Events
aaalllexxx edited this page Jun 29, 2026
·
1 revision
ENPAF has a thread-safe pub/sub system. Events flow in both directions:
-
Python → Python:
@app.on(event)handlers. -
Python → JS:
app.emit(event, data)also pushes to the WebView. -
JS → Python:
enpaf.emit(event, data)fires Python handlers. -
JS ← Python:
enpaf.on(event, handler)receives pushed events.
@app.on("app_start")
def on_start():
print("started")
@app.on("wifi_scan_result")
def on_net(net):
print(net["ssid"], net.get("rssi"))Lower-level app.events API:
app.events.on(event, handler) # subscribe
app.events.once(event, handler) # fire once, then auto-remove
app.events.off(event, handler) # remove one
app.events.off(event) # remove all for event
app.events.emit(event, *args) # Python handlers ONLY (no JS)
app.events.has_listeners(event) # bool
app.events.listener_count(event) # int
app.events.event_names() # list of active events
⚠️ app.emitvsapp.events.emit—app.emit(event, data)fires Python handlers and pushes to JS.app.events.emit(...)fires Python handlers only. If your UI isn't receiving an event, you probably used the latter.
# Python: reaches both Python handlers and JS
app.emit("download_progress", {"percent": 42})// JS: reaches Python @app.on handlers
enpaf.emit("button_clicked", { id: "save" });
// JS: receive events pushed from Python
enpaf.on("download_progress", (d) => setBar(d.percent));A handler that raises does not stop the others. Instead the emitter fires an
app_error event with the exception, the offending event name, and the handler.
(The app_error path itself is guarded against infinite recursion.)
@app.on("app_error")
def on_error(exc, event=None, handler=None):
print("handler failed:", exc)Built-in events the framework emits:
| Event | When |
|---|---|
app_start |
App has started. |
app_stop |
App is stopping. |
app_pause / app_resume
|
Activity paused / resumed (Android). |
app_error |
A handler raised an exception. |
page_load / page_unload
|
A page loaded / is unloading (sent from JS). |
bridge_connect / bridge_disconnect
|
Bridge connection state. |
Pushed by the device modules and the Android runtime. Subscribe with
@app.on(...) (Python) or enpaf.on(...) (JS):
| Event | Payload | Source |
|---|---|---|
wifi_scan_result |
one network {ssid, rssi, ...}
|
Wi-Fi |
wifi_scan_finished |
— | Wi-Fi |
wifi_connected / wifi_error
|
status | Wi-Fi |
bluetooth_device_found |
{name, address, ...} |
Bluetooth |
bluetooth_connected / bluetooth_disconnected
|
status | Bluetooth |
bluetooth_data |
received bytes/text | Bluetooth |
bluetooth_discovery_finished / bluetooth_error
|
— | Bluetooth |
nfc_tag |
{id, from_launch} |
NFC (tag tapped) |
nfc_write_result |
{written, id, ...} |
NFC (armed write done) |
nfc_open |
{uri} |
NFC (auto-open on launch) |
permission_result |
{code, granted:[...], denied:[...], results:{...}} |
Permissions |
biometric_result |
{success, error} |
Biometric |
install_status |
{status, success, message} |
PackageInstaller (Companion) |
activity_result |
{request_code, result_code, data} |
onActivityResult |
# Python side just logs; the UI gets each result too
@app.on("wifi_scan_result")
def _log(net):
print("found", net.get("ssid"))enpaf.wifi.onResult((n) => addRow(n.ssid, n.rssi));
enpaf.wifi.onFinished(() => console.log("scan done"));
enpaf.wifi.scan();Getting started
Reference
- CLI Reference
- enpaf.json Configuration
- Python API
- JavaScript Bridge
- Storage
- Events
- Device Capabilities
Building & shipping
Project