Tips & Tricks on Android

Wednesday, February 25, 2009

Hello World C program using Android Toolchain

I had reported earlier how I had gotten a C Hello World statically-linked program running on my Android phone using CodeSourcery's toolchain (on linux). Today I got a dynamically-linked Hello World program running on the phone, compiled using Android's prebuilt toolchain from the source.

It's well known that Android uses a stripped down version of libc, called bionic. When you compile your program with static linking, you don't use bionic because well, you linked statically. This is non-ideal. You want to use the bionic library on the phone, and besides you want to compile using Android's prebuilt cross-compiler arm-eabi-gcc

If you are anxious to get things working, use agcc, a perl wrapper over arm-eabi-gcc that sets up everything for you so that you can just:
$ agcc hello.c -o hello
and the resulting binary (hello) just works. Of course you should have the directory containing arm-eabi-gcc in your PATH for agcc to work.

Let's explore a bit deeper. But let me first simplify my hello program to contain just a main
$ cat hello.c int main(int argc, char* argv[]) {
return 0;
}


The minimal set of flags to pass to arm-eabi-gcc to get this working is:
$ arm-eabi-gcc -o hello hello.c -Wl,-rpath-link=/Users/nirnimesh/NIR/android/mydroid/cupcake/out/target/product/generic/obj/lib -L/Users/nirnimesh/NIR/android/mydroid/cupcake/out/target/product/generic/obj/lib -nostdlib /Users/nirnimesh/NIR/android/mydroid/cupcake/out/target/product/generic/obj/lib/crtbegin_dynamic.o -lc

Here /Users/nirnimesh/NIR/android/mydroid/cupcake is the root of my Android source.

$ file hello

hello: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), not stripped

Note that the executable binary is dynamically linked.

If you leave out -Wl,-rpath-link=/Users/nirnimesh/NIR/android/mydroid/cupcake/out/target/product/generic/obj/lib you get
/Users/nirnimesh/NIR/android/mydroid/cupcake/prebuilt/darwin-x86/toolchain/arm-eabi-4.2.1/bin/../lib/gcc/arm-eabi/4.2.1/../../../../arm-eabi/bin/ld: warning: libdl.so, needed by /Users/nirnimesh/NIR/android/mydroid/cupcake/out/target/product/generic/obj/lib/libc.so, not found (try using -rpath or -rpath-link) /Users/nirnimesh/NIR/android/mydroid/cupcake/out/target/product/generic/obj/lib/libc.so: undefined reference to `dl_unwind_find_exidx' collect2: ld returned 1 exit status

If you leave out -L/Users/nirnimesh/NIR/android/mydroid/cupcake/out/target/product/generic/obj/lib you get
/Users/nirnimesh/NIR/android/mydroid/cupcake/prebuilt/darwin-x86/toolchain/arm-eabi-4.2.1/bin/../lib/gcc/arm-eabi/4.2.1/../../../../arm-eabi/bin/ld: cannot find -lc collect2: ld returned 1 exit status

If you leave out -nostdlib you get
/Users/nirnimesh/NIR/android/mydroid/cupcake/prebuilt/darwin-x86/toolchain/arm-eabi-4.2.1/bin/../lib/gcc/arm-eabi/4.2.1/../../../../arm-eabi/bin/ld: crt0.o: No such file: No such file or directory collect2: ld returned 1 exit status

If you leave out /Users/nirnimesh/NIR/android/mydroid/cupcake/out/target/product/generic/obj/lib/crtbegin_dynamic.o you get
/Users/nirnimesh/NIR/android/mydroid/cupcake/prebuilt/darwin-x86/toolchain/arm-eabi-4.2.1/bin/../lib/gcc/arm-eabi/4.2.1/../../../../arm-eabi/bin/ld: crt0.o: No such file: No such file or directory collect2: ld returned 1 exit status

And finally, f you leave out -lc your compilation fails with:
/Users/nirnimesh/NIR/android/mydroid/cupcake/out/target/product/generic/obj/lib/crtbegin_dynamic.o: In function `_start': bionic/libc/arch-arm/bionic/crtbegin_dynamic.S:(.text+0x10): undefined reference to `__libc_init' collect2: ld returned 1 exit status

So far we've been able to compile C programs using Androids toolchain and run on the phone.
To summarize, it's the most convenient to use agcc as the compiler so you don't have to bother.

Friday, February 20, 2009

cp on Android

The Android Dev Phone (and G1, by extension) does not have the cp command in the adb shell prompt. Since you can compile and run C code on the phone, you could in theory also compile the cp program but that's probably a stretch. Alternatively, you can:
cat source_file > dest_file

This works because the phone has a full-featured shell which supports stream redirection.

Screenshots on Android

If you want to report something about your phone over email, a screenshot goes a long way.

To take a screenshot you need to download the Android SDK for your machine. It includes a tool called ddms which is the dalvic debug monitor. Dalvic is the Java runtime powering all the apps on your android phone.

Connect the phone to your machine, run ddms from the terminal and go to Device > Screen Capture (or Ctrl-S) for taking a screenshot.

Hello World in C on Android

If you've been following the Android world, you'd know that Android's SDK requires you to write apps in Java. Ever since I got my phone I've been dying to run a Hello World C program, but I've been unable to get the right cross compiler for it.

Today I finally managed to do it using CodeSourcery's cross compiler on linux. A cross compiler is something which allows you to compile on one architecture (the host) and run the executable binary on another (the target). In this case, the host is the linux machine where we'll install the toolchain (linux intel x86) and android phone is the host (arm).
  1. Download CodeSourcery's toolchain installer for GNU/Linux target for IA32 host
  2. Install it: sh arm-2008q3-72-arm-none-linux-gnueabi.bin
  3. The toolchain provides the cross compiler arm-none-linux-gnueabi-gcc. You need to put it's directory in your $PATH. Once you have the toolchain, you can easily compile your hello world program: arm-none-linux-gnueabi-gcc -o hello -static hello.c
  4. Copy the binary to your phone and run it from an adb shell prompt: ./hello
Voila!

Points to note:
  • The above binary is static, that is it does not use the phone's libc libraries. Android ships with its own trimmed down version of libc, called bionic. Next I'll be trying to compile and run using bionic libc, so that I don't have to compile statically
  • The above steps do not use the toolchain in the android source code. I'll try later to cross compile using that.

Wednesday, February 18, 2009

Installing non-Market Apps on Android Phone

If you own an Android Dev phone, at some point you'd probably want to create and try your own apps (or apps from your friends).

To ensure that you do not break your phone by installing malicious apps, Android has a couple of safety features built in. So you need to specifically instruct android to be able to install unsigned / non-market apps.

Menu > Settings > Applications > Unknown Sources

Check "Unknown Sources" to allow install of non-Market applications. While developing, you most likely also want to enable "Stay awake" in Menu > Settings > Applications > Development so that your screen does not go to sleep every often.

Now you can install any app (including malicious ones) the usual way either by browsing to the app using the browser or using adb install command.