Important
This PEP is a historical document. The up-to-date, canonical documentation can now be found atUsing Python on Android.
×
SeePEP 1 for how to propose changes.
This PEP proposes adding Android as a supported platform in CPython. The initialgoal is for Android to achieve Tier 3 support in Python 3.13.
This PEP is based onPEP 730 – “Adding iOS as a supported platform” byRussell Keith-Magee, and covers many of the same issues. Notable differencesbetween the two platforms can be found by searching for the word “iOS”.
Over the last 15 years, mobile platforms have become increasingly importantparts of the computing landscape. Android is the operating system that runs onabout70% of these devices. However, thereis no official support for Android in CPython.
TheChaquopy,BeeWare andKivy projectshave all supported Android for many years, and they have all been used togenerate applications that have been accepted for publication in the Google PlayStore. This demonstrates the technical feasibility of Android support.
It is important for the future of Python as a language that it is able to beused on any platform that has widespread adoption. Otherwise, potential userswill choose other languages thatdo provide support for these platforms. Thisis especially true in education, where the next generation of developers is inmany cases already spending more time using mobile platforms than desktop ones.
Android is broadly a POSIX platform, based on a Linux kernel and theELF binary format. It does not use glibc, instead providing its own Clibrary implementation called Bionic. As a result, it is generally notbinary-compatible with any other Linux distribution, even if the architecturematches. It also has its own filesystem layout which doesn’t resemble any otherUnix.
However, Android’s source-compatibility with Linux is quite good. In its early years,the C library was very incomplete, but most of the gaps were filled by around2014. Since then, any C code that compiles for Linux can usually be compiled forAndroid, unless it involves direct access to hardware devices or operatingsystem services.
This is also true of CPython. Although it has never officially supportedAndroid, recent versions (since 3.6) can already be compiled for Android withminimal patching.
Each Android version can be identified in three ways:
There is no consistent pattern to link one of these to another; they must belooked up ina table.
A new major Android version is released each year, but the updates available toeach device are entirely under the control of its manufacturer. Unfortunatelymany manufacturers stop sending updates to devices long before their users areready to dispose of them. For example, as of October 2023, the oldest Androidversion still receiving security updates was API level 30, but according toGoogle’s own statistics, only 60%of devices were on that version or newer.
For Python 3.13 we therefore propose the minimum Android version to be 5.0(API level 21), which was released in 2014. According to the statistics above,this would cover 99% of active devices.
The Android development tools are equally supported on Linux (x86_64), Windows(x86_64) and macOS (x86_64 and ARM64). For CPython, the most important toolsare:
Binary compatibility between libraries compiled with different versions of theNDK is generally very good, but for reproducibility it would be best for eachPython version to stick with one NDK version throughout its life. For Python3.13, this would be the current NDK long-term support version, r26.
Each NDK version can be set to target any of a wide range of Android versions.For example, NDK r26 supportsAPI levels 21 to 34.However, binaries compiled for an older Android version will usually keep onworking indefinitely on newer versions; exceptions to this rule are only madefor security reasons.
These tools may all be used either from the command line, or through the AndroidStudio IDE, which is based on IntelliJ IDEA.
Android currently supports 4 architectures. Their names as used by the Androidtools are:
armeabi-v7aarm64-v8ax86x86_64Virtually all current physical devices use one of the ARM architectures.x86andx86_64 are supported for use in the emulator.
For Python 3.13 we propose that Tier 3 support will only cover the 64-bit platforms(arm64-v8a andx86_64):
x86 has not been supported as a development platform since 2020, and nonew emulator images have been released since then.armeabi-v7a’s proportion of active devices is nowless than 10% and steadily falling.It would also be more difficult to cover with a reliable buildbot, since thereare no native hosts available for the emulator (ARM64 Macs don’t have hardwaresupport for ARM32 code). Although cross-architecture emulation is possible, ithas much worse performance and stability, which is why thearmeabi-v7aemulator images have not been updated since 2016.
However, it continues to be used for watches and ultra-low-cost phones. Ifthis persists, we may need to consider adding it in a future Python version.
Even if 32-bit architectures are not officially supported, no changes should bemade which would impede any downstream projects which still wish to build them.
The primary programming language in Android apps is Java, or its modern descendantKotlin. As such, an app does not provide its own executable file. Instead, allapps start off as a Java virtual machine running an executable provided by theoperating system. The app’s Java code can then add native code to the process byloading dynamic libraries and calling them through JNI.
Unlike iOS, creating subprocessesis supported on Android. However apps mayonly run executables incertain locations, none of whichare writable at runtime. Long-running subprocesses areofficially discouraged, and are notguaranteed to be supported in future Android versions.
Android does provide a command-line shell, but this is intended only for use bydevelopers, and is not available to the typical end user.
For these reasons, the recommended way of running Python on Android will be byloadinglibpython3.x.so into the main app process. Apython3.xexecutable will not be officially supported on this platform.
The focus of this work will be to produce an Android equivalent to the existingWindows embeddable package,i.e. a set of compiled libraries which developerscan add to their apps. No installer will be required.
Adding Android as a Tier 3 platform only requires adding support for compilingan Android-compatible build from the unpatched CPython source code. It does notnecessarily require there to be any officially distributed Android artifacts onpython.org, although these could be added in the future.
Android will be built using the same configure and Makefile system as otherPOSIX platforms, and must therefore be builton a POSIX platform. Both Linuxand macOS will be supported.
A Gradle project will be provided for the purpose of running the CPython testsuite. Tooling will be provided to automate the process of building the testsuite app, starting the emulator, installing the test suite, and executingit.
For the reasons discussed inApp lifecycle, Python will be included in theapp as a dynamiclibpython3.x.so library which can be loaded into an appusingdlopen.
Unlike Linux, Android does not implicitly use a dlopened library to resolverelocations in subsequently-loaded libraries,even if RTLD_GLOBAL is used. AllPython extension modules must therefore be explicitly linked againstlibpython3.x.so when building for Android.
An extension module linked againstlibpython3.x.so cannot be loaded by anexecutable that has been statically linked againstlibpython3.x.a.Therefore, a staticlibpython3.x.a library will not be supported on Android.This is the same pattern used by CPython on Windows.
This approach also allows using the-Wl,--no-undefined option to detectmissing symbols at build time, which can be a significant time-saver.
Unlike iOS, Android allows dynamic libraries to be loaded from any location, soa directory tree containing co-located .py, .pyc and .so files can be handled byPython’s standard importer.
A number of standard library modules will not be supported on Android becausethe underlying C APIs are not available:
curses andreadlinedbm.gnu anddbm.ndbmgrpmultiprocessing – although subprocesses in general are allowed (seeApplifecycle), Android does not support any part of theSystem V IPC API.tkinter andturtle – these would require an Android build of Tkitself, which is not officially supported.syssys.platform will return"android". Although Android is based on Linux,it differs in enough significant ways that a separate name is justified.
When embedded in an Android app, the C-level stdio streams are not connected toanything. So in this mode,sys.stdout andsys.stderr will be redirectedto the systemLogcat,which can be viewed with the Android development tools.sys.stdin willalways return EOF.
platformMost of the values returned by theplatform module will match those returnedbyos.uname(), with the exception of:
platform.system() -"Android", instead of the default"Linux"platform.release() - Android version number, as a string (e.g."14"),instead of the Linux kernel versionIn addition, aplatform.android_ver() method will be added, which returns anamedtuple containing the following:
release - Android version of the device, as a string (e.g."14")api_level -API level of the device, as aninteger (e.g.34)manufacturer -manufacturer ofthe device, as a string (e.g."Google")model -model name of thedevice, as a string (e.g."Pixel7")device -device name of thedevice, as a string (e.g."panther")is_emulator -True if the device is an emulator;False if it’s aphysical device.Which one ofmodel anddevice is more likely to be unique, and which oneis more likely to resemble the marketing name, varies between differentmanufacturers.
osos.uname() will return the raw result of a POSIXuname() call. This willresult in the following values:
sysname -"Linux"release - The Linux kernel version (e.g."5.10.157-android13-4-00003-gdfb1120f912b-ab10994928")This approach treats theos module as a “raw” interface to system APIs, andplatform as a higher-level API providing more generally useful values.
Since Android emulators and physical devices use the same ABI, and come withidentical or very similar operating system binaries, testing on emulators willbe adequate. x86_64 emulators can be run on Linux, macOS or Windows, but ARM64emulators are only supported on ARM64 Macs.
Anacondahas offeredto provide physical hardware to run Android buildbots. These will include bothLinux x86_64 and macOS ARM64 machines, which would cover both supported runtimearchitectures and both supported build platforms.
CPython does not currently test Tier 3 platforms on GitHub Actions, but if thisever changes, their Linux and macOS runners are also able to host Androidemulators. macOS ARM64 runners have been free to all public repositoriessince January 2024.
Android wheels will use tags in the formatandroid_<api-level>_<abi>. Forexample:
android_21_arm64_v8aandroid_21_x86_64For the meaning of<api-level>, seeOS versions. In the context ofthe wheel tag, it indicates the minimum Android version that was selected whenthe wheel was compiled. Installation tools such as pip should interpret this ina similar way to the existing macOS tags, i.e. an app with a minimum API levelof N can incorporate wheels tagged with API level N or older.
This format originates from the Chaquopy project, which currently maintains awheel repository with tags varying betweenAPI levels 16 and 21.
However, relying on a small group of Android enthusiasts to build the wholePython ecosystem is not a scalable solution. Until prominent libraries routinelyrelease their own Android wheels, the ability of the community to adoptPython on Android will be limited.
Therefore, it will be necessary to clearly document how projects can add Androidbuilds to their CI and release tooling. Adding Android support to tools likecrossenv andcibuildwheel may be one way to achieve this.
The Android wheel tag format should also be added to the list of tags acceptedby PyPI.
PEP 11 will be updated to include the two supported Android ABIs. Autoconfalready identifies them with the following triplets:
aarch64-linux-androidx86_64-linux-androidPetr Viktorin will serve as the initial core team contact for these ABIs.
Adding a new platform does not introduce any backwards compatibility concerns toCPython itself. However, there may be some backwards compatibility implicationson the projects that have historically provided CPython support (i.e., BeeWareand Kivy) if the final form of any CPython patches don’t align with the patchesthey have historically used.
Adding a new platform does not add any new security implications.
The education needs related to this PEP relate to two groups of developers.
First, developers ofapps need to know how to build Python into an Androidapp, along with their own Python code and any supporting packages, and how touse them all at runtime. The documentation will cover this in a similar form tothe existingWindows embeddable package.However, it will recommend most developers to use higher-level tools such asBriefcase,Chaquopy andBuildozer, all of which already havecomprehensive documentation.
Second, developers ofpackages with binary components need to know how tobuild and release them for Android (seePackaging).
TheChaquopy repository contains a referencepatch and build scripts. These will have to be decoupled from the othercomponents of Chaquopy before they can be upstreamed.
Briefcase provides a referenceimplementation of code to execute test suites on Android devices and emulators.TheToga Testbed is anexample of a test suite that is executed on the Android emulator using GitHubActions.
The following changes were made to the original specification ofplatform.android_ver():
min_api_level field was removed, because unlike all the other fields,it isn’t a property of the current device. This information is still availablefrom the pre-existing functionsys.getandroidapilevel().is_emulator field was added, since experience during testing showedthat some issues were emulator-specific.This document is placed in the public domain or under the CC0-1.0-Universallicense, whichever is more permissive.
Source:https://github.com/python/peps/blob/main/peps/pep-0738.rst
Last modified:2024-10-07 17:43:06 GMT