Skip to content

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.