What ApkPy reaches, and what it does not¶
Most tools tell you what they do. This page also tells you what they do not, because that is the half you need before you start building and the half that is usually missing.
Everything here was measured against android.jar from API 35 — the same file
the build compiles against — not estimated.
The number you would put on a slide¶
| Measure | ApkPy | The platform | |
|---|---|---|---|
android.* classes referenced |
167 | 2,585 | 6.5% |
android.* packages touched |
31 | 186 | 16.7% |
System services (getSystemService) |
9 | 97 | 9.3% |
| Permissions it knows how to declare | 20 | 322 | 6.2% |
That is the honest number, and it is small.
It is also close to meaningless. Most of that denominator is not something an
app uses: android.renderscript is 48 deprecated classes, android.icu.text
is 55 classes of the ICU library, android.health.connect.datatypes is 59
classes of one feature, and there are whole packages for device administration
and carrier services that a normal application never touches. "6.5% of the
Android API" is as true as it is useless.
So here is the other count, with the list attached, so you can argue with it instead of believing it.
The count that means something¶
Sixty capabilities an application actually uses. ApkPy covers all 60. Until 1.13.0 it was 43; the seventeen that moved are marked below, and some of them are a narrower yes than the words suggest.
The list is ours. That is exactly why it is printed in full.
Screens¶
| yes | screens and navigation |
| yes | bottom bar and drawer |
| yes | lists and virtual collections |
| yes | light/dark theme at run time |
| yes | your own typefaces |
| yes | Markdown and rich text |
| yes | maps |
| yes | charts (since 1.12.0) |
| yes | a web page, over the app or inside it (since 1.13.0) |
Data¶
| yes | key-value storage |
| yes | typed SQLite |
| yes | HTTP with JSON |
| yes | WebSocket |
| yes | files and uploads |
| yes | encryption and keys |
| yes | saving a file where the person chooses (since 1.13.0) |
| yes | downloads by the system (since 1.13.0) |
Background¶
| yes | background work that survives the app |
| yes | notifications |
| yes | push (Firebase) |
| yes | continuous location |
| yes | scheduled tasks |
The device¶
| yes | camera and gallery |
| yes | embedded camera |
| yes | barcodes and QR |
| yes | motion sensors |
| yes | location |
| yes | biometrics |
| yes | NFC |
| yes | Bluetooth and BLE |
| yes | flashlight |
| yes | battery |
| yes | wallpaper |
| yes | contacts |
| yes | clipboard |
| yes | vibration and haptics (since 1.13.0) |
| yes | recording audio (since 1.13.0) |
| yes | reading text aloud (since 1.13.0) |
| yes | dictation (speech to text) (since 1.13.0) |
| yes | adding to the calendar (since 1.13.0) |
| yes | the dialler and messages (since 1.13.0) |
| yes | printing and PDF (since 1.13.0) |
| yes | health data (Health Connect) (since 1.13.0) |
Media¶
| yes | playing audio |
| yes | video |
| yes | sharing to other apps |
| yes | receiving a share from another app (since 1.13.0) |
System¶
| yes | runtime permissions |
| yes | languages |
| yes | crash reports |
| yes | accessibility checks |
| yes | app inspection |
| yes | in-app purchases |
| yes | OAuth sign-in |
| yes | your own Java |
| yes | links that open your app (since 1.13.0) |
| yes | home-screen widget (since 1.13.0) |
| yes | quick settings tile (since 1.13.0) |
| yes | ads (AdMob) (since 1.13.0) |
| yes | updates through Play (since 1.13.0) |
What a "yes" does not mean¶
Seventeen of these became "yes" in 1.13.0, and several are a narrower yes than the words suggest. Better said here than found out later:
- A web page is a page over the whole screen — in the person's browser or inside the app. It is not a web view placed among other components.
- The calendar is adding an event, which the person saves. Reading their calendar is not there.
- The dialler and messages open with everything filled in and the person presses the last button. Calling or sending without them is a permission Google Play keeps for diallers and SMS apps, and ApkPy does not ask for it.
- Links that open your app: a scheme of your own (
notes://) works at once.https://links work too, but Android asks the person which app to use until your site publishes the file that names the app. - A home-screen widget is one widget with one design: a title, a large text, a caption and an icon, in a row or as a card. No list, no buttons, no picture. It changes when a screen of the app says so, not from a background job.
- A quick settings tile shows a state and opens the app. It does not run your Python with the app closed.
- Health data is read, not written, as one number for a stretch of time (the steps of a day, a week's average heart rate), on Android 14 and newer. The records themselves — each heartbeat, each sleep stage — are not there.
- Updates through Play work for a copy of the app installed from Play. A build installed over a cable can only answer that it is not one.
- Ads are AdMob's banner, interstitial and rewarded formats. Native ads laid out among your own components, app-open ads and mediation networks are not there.
What a "no" costs you¶
Nothing on this list is a "no" any more. What is narrower than you need is
reached the way it always was: native.gradle() pulls a library in, and
your own Java — or, since 1.13.0, Java written as
Python — reaches any Android class ApkPy has no call for.
The other ceiling¶
Coverage is the question everyone asks. It is not the one that stops apps
growing. Until 1.10.0 an application had to live in a single writehere.py,
so every screen, callback and helper landed in one file.
More than one file changed that, and since 1.14.1 a file
can hold classes too. That matters more than any single item on the list
above.
How these numbers were produced¶
- Classes, packages: every fully qualified
android.*name the compiler, the feature modules and the Java sidecars can emit, checked against the classes that really exist inandroid.jar(10 of the 177 matches were permission and intent strings, not classes, and were dropped). - System services: the
*_SERVICEconstants declared onandroid.content.Context. - Permissions: the constants on
android.Manifest.permission. - Capabilities: our list of sixty, each decided by a named signal in the source — a public API name, or a specific Android class in the generated Java. Printed above in full so the list can be checked rather than trusted.
The four counts in the first table were taken at 1.10.0 and have not been taken again, so they are lower than the truth: 1.13.0 alone added text to speech, speech recognition, the print manager, the download manager, app widgets, tile services and Health Connect. The list of sixty is current as of 1.13.0, which moved seventeen items from "no" to "yes"; 1.12.0 had moved charts.
See also Compatibility and limits for the Python ApkPy translates, and Can ApkPy build this? for whole app types rather than single capabilities.