• The KBOX project
• Articles about software development
Building and running native code utilities on Android without ADB or rooting
This article describes a straightforward way to run simple native-code utilities such as a telnet client or server on an Android device, without all the hassle of rooting the device, or pushing binaries using ADB. By 'simple' I mean
console-mode utilities that have few, if any, dependencies, and don't need
root privileges. Despite common misconceptions, you don't need root
privileges to run utilities like
although you do have to be careful about IP port numbers, and other
considerations which I'll get to below. This procedure could, in principle,
be used to install complex applications or sets of applications, but
it would most likely be so fiddly that full-on rooting would be less hassle.
Most Android devices can be 'rooted', i.e., have their built-in application
sandboxing mechanisms completely circumvented. Usually this involves
a fairly invasive procedure of replacing the bootloader and kernel. In
this article I'm specifically dealing with stock, unrooted devices. The
procedure will work on rooted devices but, quite honestly, there would be
This is not a method of rooting your device, or of circumventing any of
Android's built-in security or sandboxing measures. As I said, many of
the native code utilities I want to run will co-exist quite happily with
Android security. Nothing I describe here is subversive, or even undocumented.
Google does describe a way to execute native binaries by bundling them
.apk files and unpacking them into app storage.
What I'm describing amounts to the same thing, but without the administrative
overhead of building the
.apk file. So it's not secret,
but there doesn't seem to be a straightforward, step-by-step
procedure written up anywhere. For the sake of example, I will describe
building and installing a simple telnet server,
that will let me log into my Xoom tablet remotely. I'll describe
installation first, because there are plenty of pre-built binaries
floating around the Web and not everybody wants to install a compiler
toolchain just to run
vim or whatever.
The method I'm describing has been tested on Android versions 3.x and later.
It might work on other devices, but I haven't tried. Android is moving
so quickly that, by the time you read this, the method may no longer work.
In which case, sorry. I'm assuming a fair amount of general Linux knowledge — but then I suspect that nobody but a Linux developer would be remotely
interested in any of this.
What you need
To install pre-built binaries you will need a terminal emulator (both to install them in the right place and to run them), and some way of getting your
files onto the device.
To build, you'll need a cross-compiler toolchain for ARM. I'm using the
official Google Android NDK. There are all sorts of problems with this,
but it's good enough for my purposes.
Installing a native binary
It would be nice if you could put native binaries directly onto the
SD card (either external or built-in) but you can't. Well, you can — but you won't be able to set execute permissions on them, which means
they won't run. The SD card is mounted in such a way as to prohibit
setting 'x' permissions. You can set execute permissions in the app
storage area — that part of the filesystem that is rooted at
/data/data. On an unrooted device you won't be able to
create files just anywhere in this directory, because each app
has its own security credentials — effectively each app runs as a different
user. Only one directory under
/data/data will be writeable
by a specific app. Once you've found that directory, you can copy
a binary into it, and run it at the terminal emulator prompt.
From the above, it should be clear that a straightforward place to write
binaries is in the app storage area that belongs to your terminal emulator.
There are various terminal emulators around — I am using the implementation
written by Jack Palevich (thanks) which is available free of charge from
the Android Market. Whatever terminal emulator you use, it is crucial
that you know its internal package name. I don't believe that this is
exposed anywhere that is easy to get at, but a simple way to find out is
to ask the developer. In the case of Mr Palevich's product, the internal
The writeable storage area for this app will therefore be
/data/data/jackpal.androidterm/shared_prefs. There are
other directories under
jackpal.androidterm, but these
are probably not writeable. So — remember the writeable directory name.
Now you need a way to get the binary onto the device. You can use a wifi or
3G connection for this, or copy it direct using USB. So long as you can
identify the Linux directory where the file comes in, that is sufficient.
I run a Web server on my development machine, and use the built-in
browser on my tablet to download binaries from there. The
built-in browser by default
stores downloads in the
Download directory, which seen from
the Linux level is
So, assuming I've downloaded the
utelnetd utility using
the browser, I can copy it into an executable location using the
terminal emulator simply by starting it, and running the following
$ cd /data/data/jackpal.androidterm/shared_prefs
$ cat /sdcard/Download/utelnetd & utelnetd
$ chmod 755 utelnetd
If you've copied the file via USB, then it will be somewhere else under
/sdcard — doesn't matter where, so long as you can find it.
Incidentally, you might think you could do 'cp' rather than 'cat' in
step 2 above, but you can't. Android won't let you create a file with
execute permissions, but it will let you create a file without, and then
set execute permissions on it. Answers on a postcard, please.
Now you can run the telnet server:
$ ./utelnetd -p 1025 -l /system/bin/sh
This command-line does illustrate some of the limitations of this technique.
-p 1025 argument tells the telnet server to listen on
port 1025. Typically a telnet server uses port 23, but port 23 is not
available to a non-root process (nor any other port below 1024). That's
no problem, except that you'll
have to tell your telnet client to use port 1025 rather than the default.
-l /system/bin/sh tells
utelnetd to use the
specified executable as the login program. Android does not have a
login infrastructure (so far as I know), so you can't specify
/bin/login as you might on a full-scale Linux machine.
You can't even specify
/bin/sh because there's nothing
/bin in a stock Android device — the
usual Linux utilities like
It will be clear now, I hope (if it wasn't already), why running complex
applications this way is likely to be very fiddly. Quite apart from
the security limitations imposed by Android on the code you run, the
Android filesystem layout is not very Linux-like. If you're running something
that is hard-coded to find dependent libraries in (say)
/usr/lib/[app_name] you're going to be out of luck — this directory does not even
exist, and you can't create it. Many conventional files and directories
are not where you might expect them to be, and it could be quite difficult
to modify complex applications to account for that.
But for simple things, it's OK.
One last point: whatever you run using this method will run with the
privileges of the terminal emulator. The terminal emulator will probably
have rights to read and write the SD card, and make network connections.
The rights an Android app gets are specified by the developer when the
app is packaged. This leads to the anomalous situation that your native-code
privileges are controlled by the developer of the terminal emulator you
use to run them. Isn't Android wonderful?
Building native code uilities
For relatively simple C applications, this is surprisingly easy these
days. The latest version of the Android Native Development Kit (NDK) has
a ready-made toolchain and scripts to install it in a rational way.
I believe that the NDK is available for OS/X and Windows, but I've only
used the Linux version. All versions are available from the
Android SDK Web site.
We don't need the 'ordinary' Android SDK for any of this (although if you're
interested in poking around inside Android you probably already have it),
and we certainly don't need to build Android from source. All we need to do
for this exercise is to set up the NDK pre-built toolchain. This amounts
to unpacking the distribution, and running the script
build/tools/make-standalone-toolchain.sh. This script
creates a version of the toolchain that is modified to know where
all the installed bits are, and what command-line arguments to use.
All the binaries are provided in the distribution —
make-standalone-toolchain simply provides a simply way to use them.
Without this step you need to specify a whole bunch of file location
gcc which is a drag. It's particularly a
drag if you porting an application and you don't want to fiddle around with
its build machinery (Makefile, etc).
So I would run
make-standalone-toolchain like this:
$ buld/tools/make-standalone-toolcharin.sh --platform=android-9 \\
Thereafter I can run the
gcc compiler like this:
Or more likely, if I have a Makefile:
For the telnet server example I referred to above, I got the single source
Then to compile it for Android:
arm-linux-androideabi-gcc -o utelnetd utelnetd.c
And that's it. In this case no changes were necessary to make it work
on Android, although I would not expect such good fortune with more complicated
So it's possible to build and run native code utilities for Android without
rooting and other invasive procedures. Such utiltities will run with the
permissions of the terminal emulator that started them, and will remain
subject to Android's security restrictions. So far as I know, what
I'm describing is in keeping with Android's security model and is not
a 'hack' of any kind. It probably does not have many applications, but
it's a lot simpler and less invasive than rooting for those applications it