Applications for Android/Linux are markedly different from applications constructed with the Android SDK. Applications built with Eclipse and the context-sensitive Java syntax tools make for a comfortable learning environment. In line with the spirit of Linux development, from here on out all development takes place with command- line tools and nothing more sophisticated than a text editor. Though the Eclipse envi- ronment could certainly be leveraged for non-Java development, the focus of this chapter is on core C language1 coding for Android/Linux. The first place to start is with the cross-compiling tool chain required to build Android/Linux applications.
13.1.1 The C compiler and linker tools
Building applications for Android/Linux requires the use of a cross-compiler tool chain from CodeSourcery. The specific version required is the Sourcery G++ Lite Edition for ARM, found at https://support.codesourcery.com/GNUToolchain/release1479.
Once installed, the Sourcery G++ tool chain contributes a number of useful tools to assist you in creating applications targeting Linux on ARM, which is the architecture of the Android platform. The ARM platform is a 32-bit reduced instruction set computer
1 For details on the C programming language, start here: www.cprogramming.com/.
(RISC) processor, used in numerous devices, including smartphones, PDAs, and tech- nology appliances such as low-end routers and disk drive controllers. The Code- Sourcery installation comes with a fairly comprehensive set of PDF documents describing the main components of the tool chain, including the C compiler, the assembler, the linker, and many more tools. A full discussion of these versatile tools is well beyond the scope of this chapter, but three tools in particular are demonstrated in the construction of this chapter’s sample applications. You’ll be using these tools right away, so let’s briefly introduce them in this section.
The first and most important tool introduced is gcc.2 This tool is the compiler responsible for turning C source files into object files and optionally initiating the link process to build an executable suitable for the Android/Linux target platform. The full name of the gcc compiler for our cross-compilation environment is arm-none- linux-gnueabi-gcc. This tool is invoked from the command line of the development machine. The tool takes command-line arguments of one or more source files, along with zero or more of the numerous available switches.
The linker, arm-none-linux-gnueabi-ld, is responsible for producing an execut- able application for our target platform. When performing the link step, object code along with routines from one or more library files are combined into a relocatable, executable binary file, compatible with the Android Emulator’s Linux environment.
Whereas a simple application may be compiled and linked directly with gcc, the linker is used when creating applications with more than one source file and/or more com- plex application requirements.
If the linker is responsible for constructing applications from more than one con- tributing component, the object dump utility is useful for dissecting, or disassembling, an application. The objdump, or arm-none-linux-gnueabi-objdump tool examines an executable application—a binary file—and turns the machine instructions found there into an assembly language listing file, suitable for analysis.
NOTE All of the examples in this chapter take place on a Windows XP work- station. It’s also possible to use this tool chain on a Linux development machine. If you are using Linux for your development environment, you may need to modify the build scripts slightly as the path separator is different and the libraries will require a preceding dot (“.”).
With this brief introduction behind us, let’s build the obligatory Hello Android appli- cation to run in the Linux foundation of the Android Emulator.
13.1.2 Building a Hello World application
The first thing we want you to accomplish with your journey into Android/Linux development is to print something to the emulator screen to demonstrate that you’re running something on the platform outside the Android SDK and its Java application environment. There’s no better way to accomplish this feat than by writing a variant of
2 For everything you’d want to know about gcc, go here: http://gcc.gnu.org/.
the Hello World application. At this point, there will be little talk of Android activities, views, or resource layouts. Most code samples in this chapter are in the C language.
The following listing shows the code for your first Hello Android application.
#include <stdio.h>
int main(int argc,char * argv[]) {
printf("Hello, Android!\n");
return 0;
}
Virtually all C language applications require an #include header file containing func- tion definitions, commonly referred to as prototypes. In this case, the application includes the header file for the standard input and output routines, stdio.h. The stan- dard C language entry point for user code is the function named main. The function returns an integer return code (a value of 0 is returned in this simple example) and takes two arguments. The first, argc, is an integer indicating the number of com- mand-line arguments passed in to the program when invoked. The second, argv, is an array of pointers to null-terminated strings representing each of the command-line arguments. The first argument, argv[0], is always the name of the program execut- ing. This application has but a single useful instruction, printf, which is to write to standard output (the screen) a textual string. The printf function is declared in the header file, stdio.h.
To build this application, you employ the gcc tool:
arm-none-linux-gnueabi-gcc hello.c -static -o hellostatic
You’ll notice a few things about this command-line instruction:
The compiler is invoked with the full name: arm-none-linux-gnueabi-gcc.
The source file is named hello.c.
The –static command-line switch is used to instruct gcc to fully link all required routines and data into the resulting binary application file. In essence, the application is fully standalone and ready to be run on the target Android Emulator without any additional components. An application that’s statically linked tends to be rather large, because so much code and data are included in the executable file. For example, this statically linked application with basically a single line of code weighs in at around 600 KB. Ouch! If this -static switch is omitted, the application is built without any extra routines linked in. In this case, the application will be much smaller, but it’ll rely on finding compatible routines on the target system in order to run. For now, let’s keep things simple and build the sample application in such a manner that all support routines are linked statically.
The output switch, -o, is used to request that the executable application be assigned the name hellostatic. If this switch isn’t provided, the default applica- tion name is a.out.
Listing 13.1 Hello.c
Now that the application is built, it’s time for you to try it out on the Android Emula- tor. To do this, you’ll rely on the adb tool introduced in chapter 2.
13.1.3 Installing and running the application
In preparation for installing and running the Hello Android application, let’s take a tour of our build and test- ing environment. You need to identify four distinct envi- ronments and tools and clearly understand them when building applications for Android/Linux: Android Emula- tor, command-line CodeSourcery tools, adb or DDMS, and adb shell.
The first environment to grasp is the big-picture archi- tecture of the Android Emulator running essentially on top of Linux, as shown in figure 13.1.
As presented in the early chapters of this book, there’s a Linux kernel running underneath the pretty, graphical face of Android. There exist device drivers, process lists, and memory management, among other elements of a sophisticated operating system.
As shown in the previous section, you need an environment in which to compile your C code. This is most likely to be a command-prompt window on a Windows machine, or a shell window on a Linux desktop machine, exercising the Code- Sourcery tool chain. This is the second environment you need to be comfortable operating within.
The next requirement is to copy your newly constructed binary executable applica- tion to the Android Emulator. You can do so with a call to the adb utility or by using the DDMS view in Eclipse. Both of these tools were demonstrated in chapter 2. Here’s the syntax for copying the executable file to the Android Emulator:
adb push hellostatic /data/ch13/hellostatic
Cross compiling
The CodeSourcery tool chain isn’t designed to run on the Android/Linux environment itself, so the development work being done here is considered to be cross-compiling.
The figures and example code presented in this chapter were taken from a Windows development environment used by one of the authors. There are a number of long path and directory structures in the Android SDK and the CodeSourcery tools. To help simplify some of the examples and keep certain command-line entries from running over multiple lines, we set up some drive mappings. For example, a drive letter of m:
seen in scripts and figures corresponds to the root location of source code examples on the author’s development machine. Likewise, the g: drive points to the currently installed Android SDK on the author’s development machine. Note that this tech- nique may also be used in Linux or Mac OS X environments with a “soft link” (ln) command.
Figure 13.1 Android runs atop a Linux kernel.
Note a few items about this command:
The command name is adb. This command takes a number of arguments that guide its behavior. In this case, the subcommand is push, which means to copy a file to the Android Emulator. There’s also a pull option for moving files from the Android Emulator filesystem to the local development machine’s hard drive.
After the push option, the next argument, hellostatic in this case, represents the local file, stored on the development machine’s hard drive.
The last argument is the destination directory (and/or filename) for the trans- ferred file. In this sample, you’re copying the hellostatic file from the current working directory to the /data/ch13 directory on the Android Emulator.
Be sure that the desired target directory exists first! You can accomplish this with a mkdir command on the adb shell, described next.
The final tool to become familiar with is the shell option of the adb tool. Using this command, you can interact directly on the Android Emulator’s filesystem with a limited shell environment. To enter this environment (assuming the Android Emula- tor is already running), execute adb shell from the command line. When invoked, the shell displays the # prompt, just as if you’d made a secure shell (ssh) or telnet con- nection to a remote Unix-based machine. Figure 13.2 shows these steps in action.
Note the sequence shown in figure 13.2. First the application is built with a call to gcc. Next you push the file over to the Android Emulator. You then connect to the Android Emulator via the adb shell command, which gives you the # prompt, indi- cating that you’re now in the shell. Next you change directory (cd) to /data/ch13.
Remember that this is Linux, so the application by default may not be executable. A call to chmod sets the file’s attributes, tuning on the executable bits and allowing the application to be invoked. Finally, you invoke the application with a call to ./hello- static. The search path for executable applications doesn’t by default include the cur- rent directory on a Linux system, so you must provide a more properly qualified path, which explains the ./ prefix. Of course, you can see that the application has run suc- cessfully because you see the “Hello, Android!” text displayed on the screen.
Figure 13.2 The build, copy, run cycle
Congratulations! You have a successful, albeit simple, Android/Linux application running on the Android Emulator. In the next section, we look at streamlining this build process by combining the multiple build operations into a script.
13.1.4 C application build script
In the previous section, we reviewed each step in building and preparing to test our application. Due to the rather tedious nature of executing each of these steps, you likely want to utilize command-line tools when building C applications, as it greatly speeds up the edit, compile, copy, debug cycle. This example with only a single C source file is rather simplistic; when multiple source files must be linked together, the thought of having a build script is appealing. The need for a build script (shown in listing 13.2) is particularly evident where there are numerous source files to compile and link, a situation you’ll encounter later in this chapter.
This listing shows the build script for our Hello Android application.
arm-none-linux-gnueabi-gcc hello.c -static -o hellostatic g:\tools\adb push hellostatic /data/ch13 g:\tools\adb shell "chmod 777 /data/ch13/hellostatic"
A call to arm-none-linux-gnueabi-gcc compiles the source file, hello.c. The file is statically linked against the standard C libraries, and the resulting binary executable file is written out as hellostatic. The file hellostatic is copied to the Android Emulator and placed in the directory /data/ch13. The permissions for this file are changed, permitting execution. Note the use of the adb shell with a quote-delimited command.
Once this command executes, the adb application exits and returns to the Windows command prompt.
This example can be extended to perform other build steps or cleanup proce- dures such as removing temporary test data files on the Android Emulator or any sim- ilarly helpful tasks. As you progress, it’ll become clear what commands you need to put into your build script to make the testing process more efficient.
Now that the pressure is off—you’ve successfully written, built, and executed an application in the Android/Linux environment—it’s time to deal with the problem- atic issue of a simple application requiring such an enormous file size!