In late 2008, I spent two days trying to get Python running on my Android G1. When that stalled, I tried Lua instead — and had it cross-compiled and running in an afternoon. That small win kicked off a project that eventually became an official Google open source release and put scripting languages on hundreds of thousands of Android devices.
Getting Lua and Python onto Android
The G1 ran Android 1.0 on a 528 MHz ARM processor with 192 MB of RAM. There was no NDK yet. Cross-compiling anything for Android meant building the full Android source tree, grabbing the agcc wrapper script, and patching out every localeconv() call that bionic’s libc didn’t support.
Lua was the easy one — two small patches to llex.c and lvm.c to replace localeconv and strcoll, a cross-compile with agcc, and adb push to /data. It ran on the first try.
Python 2.4.5 was harder. The build system assumed it could run the interpreter it was building (for pgen and compileall.py), so I had to split the build into a host Python and a target Python with HOSTPYTHON and HOSTPGEN variables patched into the Makefile. The posix module had to be ripped out entirely — bionic didn’t support half the POSIX calls it needed. Several modules (_ssl, readline, _curses, zlib) were disabled. After two days of patching pwdmodule.c, socketmodule.c, fileobject.c, and pystrtod.c, Python booted on the phone.
Wrapping It Up: ASE
Once I had interpreters running, the obvious next step was making them actually useful — not just a shell on a phone, but a way to script Android itself. I built the Android Scripting Environment (ASE), a host app that provided:
- An on-device script editor and terminal
- A JSON RPC bridge between scripts and Android APIs (sensors, location, SMS, Bluetooth, TTS, camera, contacts, WiFi, and more)
- A la carte interpreter installation (Python, Lua, Perl, JRuby, BeanShell, Tcl, JavaScript via Rhino, and Shell)
- Script sharing via QR codes — scan a barcode, get a running script
- Shortcuts and widgets to launch scripts from the home screen
The key architectural idea was the RPC layer. Scripts in any language could call droid.makeToast('hello') or droid.startLocating() without knowing anything about Android’s Java APIs. The AndroidProxy class exposed annotated @Rpc methods over a local JSON-RPC server, and each language got a thin client module.
ASE launched in June 2009 with a post on the Google Open Source Blog. The reception was immediate — it hit Hacker News, Reddit, and the Android developer community hard.
The Evolution: r8 through r25
Over the next year, ASE went through rapid iteration. A few highlights from the release cycle:
Interpreter expansion. What started as Python and Lua grew to include Perl, JRuby, BeanShell, Tcl, JavaScript (via Rhino), and Shell. JRuby was painfully slow — up to a minute for the first startup on a G1 — but it worked.
API surface growth. The facade started with location and sensors. By r25, it covered SMS (send, read, manipulate), Bluetooth (including binary read/write via base64), camera and video, WiFi scanning, screen brightness and timeout, battery management, airplane mode, DTMF tone generation, contact database access, media volume control, cell tower location, and various UI dialogs (date picker, time picker, seek bar, spinner).
Developer experience. The built-in editor gained Save & Run, auto-completion of brackets and quotes, and an API browser with code generation (long-tap a method to insert a call). The terminal got fullscreen mode and multiple font sizes. A logcat viewer was added. Scripts could run in the background, and a Script Monitor let you view, stop, and reconnect terminals to running scripts.
Triggers. Scripts could be scheduled to run periodically or in response to events (ringer mode changes, phone state).
Script sharing. Beyond QR codes, ASE added Locale plugin support (trigger scripts from Locale conditions) and live folders on the home screen.
Becoming SL4A
In July 2010, ASE was renamed to Scripting Layer for Android (SL4A). The rename reflected a shift in architecture: interpreters were split out into separate APKs, and SL4A became a focused runtime layer. The key addition in the SL4A era was the WebView API, which let scripts build actual GUIs using HTML/JavaScript backed by Python or any other interpreter. Scripts could also be packaged as standalone APKs that didn’t require SL4A to be installed.
SL4A continued through r3, adding context menus (later replaced with quick-action bubbles), folder support in the script manager, and in-process interpreter support. The last release in this sequence was October 2010.
What People Built
The most satisfying part of running an open source project is seeing what people do with it. ASE/SL4A users built:
- Automated data logging to your.flowingdata with home screen shortcuts for “goodmorning” and “goodnight”
- DTMF dialers for placing calls through landlines
- Home automation controllers
- Bluetooth serial bridges to Arduino and LEGO NXT robots
- GPS loggers and geocaching tools
- SMS autoresponders
The project’s niche was clear: it wasn’t for building polished apps. It was for people who wanted to script their phone the way they’d script a Linux box.
From Scripting to Robots
SL4A had an unexpected second act. Because it ran a full Python interpreter on Android, it became the first way to load ROS onto a phone — you could run rospy on SL4A and suddenly an Android device was a ROS node with cameras, GPS, an IMU, and a cellular radio. People started strapping phones to robots as cheap sensor packages, and projects like Cellbots (Ryan Hickman’s work) used SL4A to bridge Android to LEGO NXT bricks and Arduino boards over Bluetooth.
But running rospy on SL4A had real limits. Python on a 1 GHz ARM chip with 512 MB of RAM was slow, and the scripting layer added overhead on top of that. The experience convinced me that if ROS was going to run well on Android, it needed a native Java implementation — not a Python interpreter shoehorned onto a phone. That’s what led me to build rosjava, a pure Java implementation of ROS that ran natively on Android without SL4A in the loop.
Rosjava launched at O 2011 alongside Android’s Open Accessory API, and the cloud robotics work grew from there — talks at Berkeley, Devoxx, and ROSCon, and eventually Cartographer, a SLAM backpack that mapped building interiors for Google Maps. Cartographer’s Android tablet interface and parts of its infrastructure were built on rosjava. The line from “Python on a G1” to “real-time SLAM on a backpack” is surprisingly direct.
Looking Back
ASE was the right project at the right time. In 2009, Android was new, the app ecosystem was young, and the idea that you could write a Python script on your phone and have it send SMS messages was genuinely novel. The JSON RPC bridge was a pragmatic hack — it let us support any language without writing Java bindings for each one — and it held up well through the transition into robotics and beyond.
Release History
Date Release Highlights 2008-12-18 Lua on Android First cross-compiled interpreter on G1 2008-12-19 Python on Android Python 2.4.5 cross-compiled for bionic libc 2009-06-09 ASE launch Google Open Source Blog announcement 2009-06-19 r8 A la carte interpreter install, scripts on SD card 2009-07-07 r9 Orientation fix, streamlined interpreter install 2009-07-23 r10 Geocoder, event API, notifications, QR code sharing 2009-08-20 r11 Perl and JRuby support, SQLite for Python 2009-09-10 GTUG Munich Presentation at Google Technology User Group 2009-09-22 r13 New version scheme, soft keyboard, smaller APK 2009-11-01 r14 JavaScript via Rhino, ASE Server for off-device dev 2010-01-06 r15/r16 Cupcake support restored, API browser, python-twitter 2010-03-07 r17 Tcl, UI dialog APIs, speech recognition, live folders 2010-03-11 r18 Screencast help, download progress bars 2010-03-18 r19 JRuby 1.4, logcat viewer, airplane mode API 2010-03-25 r20 Trigger framework for periodic script execution 2010-04-22 r21 SMS, Bluetooth, camera APIs, code generation prompts 2010-05-03 r22 Wake locks, WiFi APIs, Locale plugin support 2010-05-14 r23 Contacts DB, DTMF tones, volume APIs 2010-06-10 r25 WebView, video, call recording, trigger service 2010-07-12 ASE → SL4A Renamed, interpreters split to separate APKs 2010-08-05 SL4A r0 Script APKs, multi-script execution, security auth 2010-08-25 SL4A r1 WebView GUI API, HTML interpreter, undo/redo 2010-09-09 SL4A r2 Quick action menus, folder support, rename scripts 2010-10-12 SL4A r3 Bluetooth binary I/O, in-process interpreter work