Device and Android API¶
| Object/API | Purpose |
|---|---|
declare_permissions / permissions |
manifest and runtime permissions |
notify |
Android system notification |
notifications |
channels, permission checks and cancellation — 1.7.0 |
push |
FCM listeners, token, topics and Preview simulation |
share |
native share sheet |
clipboard |
system clipboard |
camera / gallery |
capture and media picker (images) |
files.pick / upload_button |
pick any file type, and pick-then-upload |
location |
current, continuous and background location |
map_view |
map tiles, markers, routes and user layer |
routes / route_points |
cancellable route calculation and decoding |
service |
periodic and one-shot background work |
background_job |
persistent queue: constraints, retries, cancellation and observable progress |
biometrics |
the system fingerprint or face prompt, and why a check ended |
bluetooth |
classic serial (SPP): paired devices, lines in and out |
ble |
Bluetooth Low Energy: scan, connect, and the Nordic UART default |
nfc |
Foreground NDEF tags and one-shot writes — new in 1.9.0 |
contacts |
Scoped phone/email selection, read-only queries and native editors — new in 1.9.0 |
billing |
Play in-app purchases and subscriptions, acknowledged for you |
apps |
installed app inspection |
sensors |
shake, compass, steps, light and proximity; three new streams in the 1.7.0 |
battery |
charge percentage, charging and power-saving state |
wallpaper |
static wallpaper preview and confirmation — 1.7.0 |
haptics / speech |
a touch you can feel; reading aloud and dictation — 1.13.0 |
browser |
a web page over the app, or inside it over the whole screen — 1.13.0 |
files.save_as / downloads |
a file saved where the person chooses; a download by the system — 1.13.0 |
files.read / files.write / files.append |
text kept in the app's own files — 1.13.0 |
calendar / phone |
an event to add; the dialler and messages, filled in for the person — 1.13.0 |
recorder / printing |
the microphone; printing or a PDF — 1.13.0 |
incoming |
links and shares that open the app — 1.13.0 |
home_widget / quick_tile |
a widget on the home screen; a tile in quick settings — 1.13.0 |
ads / updates / health |
AdMob; updates through Google Play; Health Connect — 1.13.0 |
timer |
a function run later, or again and again, while its screen is on show — 1.13.0 |
network |
online or not, over what, paid for or not, and being told when it changes — 1.13.0 |
display |
staying on, brightness, the bars, which way up — 1.13.0 |
app_lock |
the app locks itself, and the phone's own lock opens it — 1.13.0 |
native.use / @native |
Android classes reached from Python, checked against android.jar — 1.13.0 |
Use Background jobs, Firebase push, Maps and continuous location and Native Android features.
From 1.13.0: The rest of the phone, Outside the app, Timers, The connection, The display, The app lock and Written in Python.
NFC — 1.9.0¶
| Method | Contract |
|---|---|
nfc.status(on_result=None) |
(True, "ready") or (False, reason) |
nfc.start(on_tag=None, on_error=None) |
Start foreground reading; on_tag(True, tag_json), on_error(False, reason) |
nfc.stop() |
Stop reading and silently cancel pending writes |
nfc.write(*, text=None, url=None, on_result=None) |
Exactly one payload; arm one attempt on the next tag; callback (ok, reason) |
nfc.cancel_write() |
Cancel an armed write; does not undo a physical write |
nfc.settings() |
Open Android NFC settings; never enable the radio automatically |
Tags are JSON text with id, type, text, url, records, writable,
size, used and tech. Reasons: unsupported, off, not_started,
no_ndef, read_only, too_small, tag_lost, unknown.
Callbacks return on the UI thread. Pausing disables reading and cancels writes.
The Previewer offers simulated tags, not real NFC. Read the
complete NFC guide for runnable code, formatting/read-back
limits, lifecycle, error recovery and excluded protocols.
Contacts — 1.9.0¶
| Method | Successful (ok, value) result |
|---|---|
contacts.pick(kind="phone", on_result=None) |
One JSON contact with the selected phone or email; kind is phone or email |
contacts.list(query="", limit=50, offset=0, on_result=None) |
JSON array, display-name substring search; limit 1–100, offset 0–100000 |
contacts.get(id, on_result=None) |
One JSON contact by numeric id or returned lookup URI |
contacts.create(name="", phone="", email="", on_result=None) |
Editor-return JSON, not a confirmed save |
contacts.edit(id, on_result=None) |
Editor-return JSON, not a confirmed save |
contacts.settings(on_result=None) |
"opened" when app settings opened |
Contact fields: id, uri, name, phone, email, phones, emails.
Editor fields: status="editor_returned", result_code="ok"|"cancelled",
uri. Callbacks receive a boolean followed by JSON text or a reason string.
Reasons: cancelled, permission_denied, permission_blocked, not_found,
unsupported, busy, invalid, unavailable, unknown.
Only list/get add and request READ_CONTACTS. The picker grants access to the
selected detail; create/edit use the system editor without WRITE_CONTACTS.
Queries run off the UI thread; callbacks return on it. Background-job calls
are rejected. No direct deletion is provided. See the
complete guide and People Desk source for permission
recovery, lifecycle, editor-return limitations and fictional Previewer data.
Notifications¶
For notify styles, callbacks, progress, grouping and permission behavior,
read the complete notification guide. It includes
copyable apps and explains where Previewer simulation differs from Android.
The extended arguments and notifications object are 1.7.0.
notify(title, message, id) remains compatible. Its optional keyword-only
arguments are channel, icon, style, picture, lines, actions,
on_tap, on_dismiss, ongoing, progress, group and when.
| Method | Contract |
|---|---|
notifications.channel(id, name, importance="default") |
Declare a channel; importance is min, low, default or high and fixed on first creation |
notifications.allowed() |
Boolean app-level permission snapshot, not a channel/delivery guarantee |
notifications.ask() |
Ask from a screen; a worker cannot open the permission dialog |
notifications.cancel(id) |
Remove one card without its user-dismissal callback |
notifications.cancel_all() |
Remove this publisher's cards, including ongoing ones |
Actions accept up to three (label, handler) pairs; handler() has no
arguments. on_tap also accepts a Screen. on_dismiss may be deferred until
the owning Activity resumes. Reusing the same ID updates a card. when is
epoch milliseconds for display, not scheduling. See the guide for styles,
static declaration restrictions, pictures, progress and lifecycle details.
Sensors and battery¶
The complete sensor guide includes runnable apps, availability checks and the Previewer simulation controls.
| Method | Callback / return type |
|---|---|
sensors.shake(on_shake=handler) |
handler() |
sensors.compass(on_change=handler) |
handler(degrees_text) |
sensors.steps(on_change=handler) |
handler(count_text) |
sensors.light(on_change=handler) |
handler(lux_text) |
sensors.proximity(on_change=handler) |
handler(near_bool) |
sensors.accelerometer(on_change=handler) — 1.7.0 release |
handler(json_text) with numeric X/Y/Z in m/s² |
sensors.gyroscope(on_change=handler) — 1.7.0 release |
handler(json_text) with numeric X/Y/Z in rad/s |
sensors.pressure(on_change=handler) — 1.7.0 release |
handler(hpa_text) |
sensors.available(name) |
boolean; pass a literal sensor name |
sensors.stop(name=None) |
stop one watch, or all watches when omitted |
battery.level() |
percentage as text |
battery.charging() / battery.saver() |
boolean snapshot |
JSON field names are lowercase x, y, z; read them with json_get.
Step counting requires activity-recognition permission on Android 10+.
The other listed sensors and battery reads do not add runtime permissions.
Check availability: the Previewer simulator is not a hardware probe.
Static wallpapers¶
| Method | Callback / return type |
|---|---|
wallpaper.available() |
boolean; checks Android support and policy |
wallpaper.set(source, target="home", on_result=None) |
on_result(success_bool, reason_text) after confirmation/error |
Targets are home, lock and both. This always shows confirmation; the
Previewer simulates success without changing the desktop. Read the
complete wallpaper guide for runnable code, image
sources, result reasons and device-testing limits. Requires ApkPy 1.7.0 or newer.
The rest of the phone — 1.13.0¶
One call each; the guide is The rest of the phone.
"Answers" is what comes back: a word at once, yes or no, or later in
on_result(ok, value).
| Call | Answers |
|---|---|
haptics.tap(), tick(), heavy(), success(), error() |
ok, off |
haptics.vibrate(ms=200) |
ok, off, no_vibrator |
haptics.available() |
yes or no |
speech.say(text, language="", rate=1.0, pitch=1.0, on_result=None) |
later: ok, stopped, no_engine, language_unavailable, failed |
speech.stop() |
ok |
speech.is_speaking() |
yes or no |
speech.listen(prompt="", language="", on_result=None) |
later: the words, or cancelled, nothing_heard, no_recogniser |
speech.can_listen() |
yes or no |
browser.open(url) |
ok, invalid, no_browser |
browser.show(url="", html="", title="", on_result=None) |
later, when closed: the last address |
files.save_as(name, text, mime="text/plain", on_result=None) |
later: the name, or cancelled, no_app, failed |
files.save_copy(path, name="", on_result=None) |
later: the name, or cancelled, not_found, no_app, failed |
downloads.start(url, name="", title="", on_result=None) |
later: the name, or invalid, no_space, failed, unavailable |
calendar.add_event(title, start, end="", location="", notes="", all_day=False) |
ok, invalid, no_app |
phone.dial(number) |
ok, invalid, no_app |
phone.sms(number, text="") |
ok, invalid, no_app |
recorder.start(on_result=None) |
later: ok, busy, permission_denied, permission_blocked, no_microphone, failed |
recorder.stop() |
the path of the .m4a, or "" |
recorder.is_recording() |
yes or no |
recorder.seconds() |
whole seconds, as text |
printing.html(html, name="Document", on_result=None) |
later: ok, unavailable, failed |
printing.text(text, name="Document", on_result=None) |
later: ok, unavailable, failed |
incoming.links(scheme, host="", preview="") |
a declaration, at the top of the file |
incoming.shares(kind="text", preview="") |
a declaration; kind is "text", "image" or "file" |
incoming.link(), incoming.text(), incoming.file() |
what arrived, or "" |
incoming.clear() |
ok |
Permissions the build adds, and only for the calls an app uses: VIBRATE
for haptics.vibrate(), INTERNET for browser.show() and
downloads.start(), RECORD_AUDIO for recorder.start(). Nothing else on
this table asks for one.
Outside the app, timers, the connection, the display and the app lock — 1.13.0¶
The guides are Outside the app, Timers, The connection, The display and The app lock.
| Family | Calls | Words it answers with |
|---|---|---|
home_widget |
define(), set(), count(), pin() |
ok, unsupported |
quick_tile |
define(), set(), is_active(), opened(), clear(), offer() |
added, already, dismissed, ok, unsupported |
ads |
setup(), banner(), hide_banner(), prepare(), interstitial(), rewarded(), consent(), needs_privacy_options(), privacy_options() |
closed, failed, invalid, network, no_fill, not_ready, ok, skipped |
updates |
check(), start(), install() |
available, cancelled, downloaded, failed, none, not_allowed, not_from_play, nothing, ok |
health |
policy(), available(), allowed(), ask(), read() |
denied, failed, invalid, no_data, no_permission, ok, unavailable |
timer |
after(), every(), cancel(), running() |
invalid, not_running, ok |
network |
online(), kind(), metered(), on_change() |
failed, ok |
display |
keep_on(), brightness(), immersive(), orientation() |
invalid, ok |
app_lock |
after(), now(), off(), locked() |
invalid, no_lock, ok |
A question (is_active(), online(), locked()) answers yes or no; count()
and kind() answer text. Exact signatures are in the
essential reference.