Android programming without an IDE
suggest changeThis is a minimalist Hello World example that uses only the most basic Android tools.
Requirements and assumptions
- Oracle JDK 1.7 or later
- Android SDK Tools (just the command line tools)
This example assumes Linux. You may have to adjust the syntax for your own platform.
Setting up the Android SDK
After unpacking the SDK release:
- Install additional packages using the SDK manager.
Don't use `android update sdk --no-ui` as instructed in the bundled Readme.txt;
it downloads some 30 GB of unnecessary files.
Instead use the interactive SDK manager `android sdk`
to get the recommended minimum of packages.
- Append the following JDK and SDK directories to your execution PATH. This is optional, but the instructions below assume it.
* JDK/bin
* SDK/platform-tools
* SDK/tools
* SDK/build-tools/LATEST *(as installed in step 1)*
- Create an Android virtual device.
Use the interactive AVD Manager (`android avd`).
You might have to fiddle a bit and search for advice;
the [on-site instructions][createAVD] aren't always helpful.
(You can also use your own device)
- Run the device:
emulator -avd DEVICE
- If the device screen appears to be locked, then swipe to unlock it.
Leave it running while you code the app.
Coding the app
- Change to an empty working directory.
- Make the source file:
mkdir --parents src/dom/domain
touch src/dom/domain/SayingHello.java
Content:
<!-- language: lang-java -->
package dom.domain;
import android.widget.TextView;
public final class SayingHello extends android.app.Activity
{
protected @Override void onCreate( final android.os.Bundle activityState )
{
super.onCreate( activityState );
final TextView textV = new TextView( SayingHello.this );
textV.setText( "Hello world" );
setContentView( textV );
}
}
- Add a manifest:
touch AndroidManifest.xml
Content:
<!-- language: lang-xml -->
<?xml version='1.0'?>
<manifest xmlns:a='http://schemas.android.com/apk/res/android'
package='dom.domain' a:versionCode='0' a:versionName='0'>
<application a:label='Saying hello'>
<activity a:name='dom.domain.SayingHello'>
<intent-filter>
<category a:name='android.intent.category.LAUNCHER'/>
<action a:name='android.intent.action.MAIN'/>
</intent-filter>
</activity>
</application>
</manifest>
- Make a sub-directory for the declared resources:
mkdir res
Leave it empty for now.
Building the code
- Generate the source for the resource declarations.
Substitute here the correct path to your **SDK**,
and the installed **API** to build against (e.g. "android-23"):
aapt package -f \
-I SDK/platforms/android-API/android.jar \
-J src -m \
-M AndroidManifest.xml -S res -v
Resource declarations (described further below) are actually optional.
Meantime the above call does nothing if res/ is still empty.
- Compile the source code to Java bytecode (.java → .class):
javac \
-bootclasspath SDK/platforms/android-API/android.jar \
-classpath src -source 1.7 -target 1.7 \
src/dom/domain/*.java
- Translate the bytecode from Java to Android (.class → .dex):
First using Jill (.class → .jayce):
java -jar SDK/build-tools/LATEST/jill.jar \
--output classes.jayce src
Then Jack (.jayce → .dex):
java -jar SDK/build-tools/LATEST/jack.jar \
--import classes.jayce --output-dex .
Android bytecode used to be called "Dalvik executable code", and so "dex".
You could replace steps 11 and 12 with a single call to Jack if you like;
it can compile directly from Java source (.java → .dex).
But there are advantages to compiling with `javac`.
It's a better known, better documented and more widely applicable tool.
- Package up the resource files, including the manifest:
aapt package -f \
-F app.apkPart \
-I SDK/platforms/android-API/android.jar \
-M AndroidManifest.xml -S res -v
That results in a partial APK file (Android application package).
- Make the full APK using the
ApkBuilder
tool:
java -classpath SDK/tools/lib/sdklib.jar \
com.android.sdklib.build.ApkBuilderMain \
app.apkUnalign \
-d -f classes.dex -v -z app.apkPart
It warns, "THIS TOOL IS DEPRECATED. See --help for more information."
If `--help` fails with an `ArrayIndexOutOfBoundsException`,
then instead pass no arguments:
java -classpath SDK/tools/lib/sdklib.jar \
com.android.sdklib.build.ApkBuilderMain
It explains that the CLI (`ApkBuilderMain`) is deprecated
in favour of directly calling the Java API (`ApkBuilder`).
(If you know how to do that from the command line, please update this example.)
- Optimize the data alignment of the APK (recommended practice):
zipalign -f -v 4 app.apkUnalign app.apk
Installing and running
- Install the app to the Android device:
adb install -r app.apk
- Start the app:
adb shell am start -n dom.domain/.SayingHello
It should run and say hello.
That’s all. That’s what it takes to say hello using the basic Android tools.
Declaring a resource
This section is optional. Resource declarations aren’t required for a simple “hello world” app. If they aren’t required for your app either, then you could streamline the build somewhat by omitting step 10, and removing the reference to the res/ directory from step 13.
Otherwise, here’s a brief example of how to declare a resource, and how to reference it.
- Add a resource file:
mkdir res/values
touch res/values/values.xml
Content:
<!-- language: lang-xml -->
<?xml version='1.0'?>
<resources>
<string name='appLabel'>Saying hello</string>
</resources>
- Reference the resource from the XML manifest.
This is a declarative style of reference:
<!-- language: lang-xml -->
<!-- <application a:label='Saying hello'> -->
<application a:label='@string/appLabel'>
- Reference the same resource from the Java source.
This is an imperative reference:
<!-- language: lang-java -->
// v.setText( "Hello world" );
v.setText( "This app is called "
+ getResources().getString( R.string.appLabel ));
- Test the above modifications by rebuilding, reinstalling and re-running the app (steps 10-17).
It should restart and say, “This app is called Saying hello”.
Uninstalling the app
adb uninstall dom.domain
See also
- original question - The original question that prompted this example
- working example - A working build script that uses the above commands