Tweet |
|
This guideline shows how to build Android programs (apps) using a command line environment only.
Even though the Eclipse IDE (among others) can be a powerful development environment for Android programmers, there are several reasons why you could benefit from utilizing simple command line utilities and build scripts instead. Actually understanding what's going on is one of them.
Using the stepwise approach outlined below might seem overwhelming, but there is a great educational value in performing these steps, and the information present is essential if you are setting up a build system based on make, SCons, Ant, or similar tools.
The setup below depends on a few environment variables identifying directory paths on the local system. The exact procedure for setting and accessing environment variables differs between operating systems and command shells. In the present guideline the simplest possible notation is being used. In practice these variables needs to be accessed using special notation like %JAVA_HOME%, ${JAVA_HOME} or even "${JAVA_HOME}" if the path contains spaces. In addition, commands are listed over multiple lines to improve readability. In practice commands must be written on a single line or separated by proper line delimiters. Note also that the forward slash character ("/") is consistently used as directory delimiter even though the backslash ("\") is still used on some systems.
Color coding is used in the commands in order to easily indicate where local replacements needs to take place.
All commands are self-contained meaning that they can be executed from any directory.
The Java Standard Edition (Java SE) is available from Oracle at http://www.oracle.com/technetwork/java/javase/downloads.
Default installation location will vary between Java versions and OS platforms, so create a pointer to its location:
JAVA_HOME = C:/Program Files/Java/jdk1.6.0_26 |
The Android Software Development Kit (Android SDK) is available from Google at http://developer.android.com/sdk.
Default installation location will vary between Android versions and OS platforms, so create a pointer to its location:
ANDROID_HOME = C:/Program Files/Android/android-sdk |
The download includes the core parts of Android. In addition you need SDK(s) for the specific Android platforms you will develop for and test on. Launch the SDK manager GUI, select Available packages and open the Android Repository:
ANDROID_HOME/tools/android |
Select the required platform/tool packages (all is fine) and hit the Install Selected button. After installation, the platform/ and platform-tools/ directories of ANDROID_HOME should have been populated.
At some disk location create a project directory that will hold the code, libraries and other files that constitutes the Android project. Create a pointer to this location:
DEV_HOME = C:/Users/johnd/dev/AndroidTest |
The project name in this context is simply a convenience in order to consistently name directories and files related to the application being created.
In the example AndroidTest is used as the project name. The term has been emphasized below so that it can be easily replaced.
Beneath the project directory create sub directories as follows:
DEV_HOME/src/com/mycompany/package1/...
res/drawable/
layout/
values/
obj/
lib/
bin/
docs/
|
The src/ directory will hold java code and other source files in
a package structure common for java projects.
Using the
reverse domain name system
(Reverse DNS) for package names is optional but recommended.
The res/ directory will hold user provided resources like
text strings,
images,
menues,
layouts
etc.
The res/ sub directories have predefined names
according to the
Android resource documentation.
The obj/ directory will contain .class files and
other secondary files produced by the Java tools as explained below.
The lib/ directory should hold 3rd-party
.jar files the project depends on.
The bin/ directory will hold intermediate and final
executables produced by the Android tools.
The docs/ directory will hold javadoc HTML documents
for the project. If generated, the docs/index.html file
will be the entry point.
The Android manifest file is used to specify application settings like name and version, as well as what permissions the application requires to run and what components it is comprised of. The file contains a single application tag inside the root manifest tag.
Put the manifest file in the project root directory: DEV_HOME/AndroidManifest.xml. Note that the file must be called AndroidManifest.xml and nothing else.
A typical manifest file is shown below:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.mycompany.package1" android:versionCode="1" android:versionName="1.0"> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-sdk android:minSdkVersion="2"/> <application android:icon="@drawable/mylogo" android:label="@string/myApplicationName"> <activity android:name="com.mycompany.package1.HelloAndroid" android:label="@string/myApplicationName"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> |
The package attribute identifies the application and is also the destination location of the generated R.java file (see below). versionCode is a numeric version value for managing application updates. versionName is the application version in a human readable form.
The application tag contains the activities of the program, one of which should contain the main launcher activity as shown.
The different Android OS versions are known through target names like android-3, android-4, android-5 etc. All available platforms can be listed by the following command:
ANDROID_HOME/tools/android list target |
For the examples below we use android-7 (Android OS 2.1) consistently. Replace this with a different target as required.
An Android Virtual Device (AVD) defines the main characteristics of the target Android device. AVDs are used only when testing an Android program in the Android emulator. The typical approach is to define several AVDs in order to verify that a program behave correct across hardware platforms and OS versions.
Use the android tool to create AVDs:
ANDROID_HOME/tools/android --verbose create avd --name MySonyEricsson --target android-7 --sdcard 1024M |
This will create an AVD with the specified name and with a 1 GB memory card disk image. When the command is executed you are asked if you want to specify a custom hardware profile. By this the AVD can be tailored to a specific hardware device by identifying properties for features like screen, camera, memory, battery, audio, accelerometer, wi-fi, bluetooth, GPS, keyboard and so on.
If no longer needed, an AVD can be deleted as follows:
ANDROID_HOME/tools/android
--verbose
delete avd
--name MySonyEricsson
|
The actual AVD profiles are stored within the HOME/.android/avd/ directory.
A keystore is a database of private keys and their associated X.509 certificate chains authenticating the corresponding public keys. An Android program must be signed in order to execute on a device, and the program is signed by using a key from a keystore.
Use the keytool program to create a keystore:
JAVA_HOME/bin/keytool -genkeypair -validity 10000 -dname "CN=company name, OU=organisational unit, O=organisation, L=location, S=state, C=country code" -keystore DEV_HOME/AndroidTest.keystore -storepass password -keypass password -alias AndroidTestKey -keyalg RSA -v |
Replace the distinguished name (dname) information with your own. Make sure to specify passwords as indicated. The key is accessed through the specified alias which can be any string.
The output of the command will be the DEV_HOME/AndroidTest.keystore file which contains one key identified by the supplied alias.
Define a suitable package structure and put the Java code within the src/ tree of the project area.
The following minimal class can serve as an example. It should be located in DEV_HOME/src/com/mycompany/package1/HelloAndroid.java:
package com.mycompany.package1; import android.app.Activity; import android.content.res.Resources; import android.os.Bundle; import android.widget.TextView; public class HelloAndroid extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TextView textView = new TextView(this); String text = getResources().getString(R.string.helloText); textView.setText(text); setContentView(textView); } } |
The Android API documentation contains a complete reference to the Android packages and classes, including the ones provided by the Java SE.
Android programmers are advised to keep all non-logic data (text strings, images, animations, colors, layouts etc.) within the designated res/ directory of the project area. The res/ directory consists of a predefined set of sub directories with a naming structure that will simplify application localization and adoption to different hardware types.
The following minimal text resource can serve as an example. It should be located in DEV_HOME/res/values/strings.xml:
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="myApplicationName">Android Test Program</string> <string name="helloText">Hello, world!</string> </resources> |
The manifest file refers to the myApplicationName entry, while the java class above refers to the helloText entry. The example manifest file above also refers to the drawable resource mylogo which is the icon image for the program. Put an image file in the res/ directory to serve this purpose: DEV_HOME/res/drawable/mylogo.png.
In order for the application source code to be able to access the resources within the res/ directory, a class called R.java (for Resources) is created.
Use the Android Asset Packaging Tool (aapt) to create the R.java file:
ANDROID_HOME/platform-tools/aapt
package
-v
-f
-m
-S DEV_HOME/res
-J DEV_HOME/src
-M DEV_HOME/AndroidManifest.xml
-I ANDROID_HOME/platforms/android-7/android.jar
|
The destination location of R.java within the src/ tree is determined by the package attribute of the manifest file.
Use the javac tool to compile java source code in a package:
JAVA_HOME/bin/javac -verbose -d DEV_HOME/obj -classpath ANDROID_HOME/platforms/android-7/android.jar;DEV_HOME/obj -sourcepath DEV_HOME/src DEV_HOME/src/com/mycompany/package1/*.java |
The command must be applied for each existing package. 3rd-party .jar files from the lib/ directory must be listed in the -classpath entry. Note that on UNIX-like operating systems the classpath entry delimiter should be a colon (":").
The output of the command is .class files in the obj/ tree.
Non-java files within the src/ tree must be copied to the associated location in the obj/ tree.
DEX ("Dalvik Executable") is the specific bytecode format understood by the Dalvik virtual machine (VM) present in all Android devices.
Use the dx tool to bundle the content of the obj/ directory as well as 3rd-party .jar files from the lib/ directory into a single .dex file:
ANDROID_HOME/platform-tools/dx --dex --verbose --output=DEV_HOME/bin/classes.dex DEV_HOME/obj DEV_HOME/lib |
This will create the classes.dex file in the bin/ directory. The content of a .dex file can be inspected using the ANDROID_HOME/platform-tools/dexdump tool.
The Android package format (APK) is the .jar equivalent for Android. The package contains the manifest file, the resources and the classes.dex file.
Use the aapt tool to create the .apk file:
ANDROID_HOME/platform-tools/aapt package -v -f -M DEV_HOME/AndroidManifest.xml -S DEV_HOME/res -I ANDROID_HOME/platforms/android-7/android.jar -F DEV_HOME/bin/AndroidTest.unsigned.apk DEV_HOME/bin |
This will create the AndroidTest.unsigned.apk file in the bin/ directory. Note that APK is an ordinary archive format that can be inspected by tools like WinZip or unzip -l.
In order to execute on an Android device, the Android package needs to be signed.
Use the jarsigner tool and the key from the keystore created above to create a signed version of the package:
JAVA_HOME/bin/jarsigner -verbose -keystore DEV_HOME/AndroidTest.keystore -storepass password -keypass password -signedjar DEV_HOME/bin/AndroidTest.signed.apk DEV_HOME/bin/AndroidTest.unsigned.apk AndroidTestKey |
The signing process adds the META-INF/ directory to the APK archive including the signature (.SF) file and the associated PKSC file (.RSA).
The signed APK is stored as AndroidTest.signed.apk file in the bin/ directory.
zipalign is an archive alignment tool that provides important optimization to Android packages. This step is optional, but recommended:
ANDROID_HOME/tools/zipalign -v -f 4 DEV_HOME/bin/AndroidTest.signed.apk DEV_HOME/bin/AndroidTest.apk |
This will create the AndroidTest.apk which is the final product delivered in one self-contained unit.
In order to test the application, start the Android emulator and specify the virtual device (AVD) to use:
ANDROID_HOME/tools/emulator
-wipe-data
-avd MySonyEricsson
|
This will launch the emulator GUI. The wipe-data option ensures the emulator starts up clean. The initialization process may take some time, so don't proceed until the emulator is ready.
When the emulator is ready, use the Android Debug Bridge (adb) tool to install the Android package in the running emulator:
ANDROID_HOME/platform-tools/adb
-e
install DEV_HOME/bin/AndroidTest.apk
|
The program should eventually show up in the emulator and can be executed by selecting it.
The application can be uninstalled as follows:
ANDROID_HOME/platform-tools/adb
shell
rm /data/app/com.mycompany.package1.apk
|
Note that inside the emulator or device the APK is stored using its main package name (from the package attribute of the manifest file) with an .apk extension.
Attach the Android device to the computer and install the program using the adb command:
ANDROID_HOME/platform-tools/adb
-d
install DEV_HOME/bin/AndroidTest.apk
|
The program should be ready for execution on the target device.
7Every well managed project should have up-to-date documentation available at any time. This step is of course optional, but strongly recommended.
Use the javadoc tool to create HTML documentation as follows:
JAVA_HOME/bin/javadoc -verbose -d DEV_HOME/docs -sourcepath DEV_HOME/src -classpath ANDROID_HOME/platforms/android-7/android.jar;DEV_HOME/obj -author -package -use -splitIndex -version -windowtitle 'AndroidTest' -doctitle 'AndroidTest' DEV_HOME/src/com/mycompany/package1/*.java |
Source from additional packages should be added to the last argument using ":" or ";" as delimiter (depending on platform).
The documentation entry point will be DEV_HOME/docs/index.html.