Since Jack and Jill are outdated, I had to modify a few commands.
Installed the sdk,ndk in /a
(the ndk is not used in this hello world), the jdk in the system, and the android-tools-adb in the /usr/bin
etc (this one contains adb and fastboot and phone definitions so that it can detect them).
I added this to .bashrc
:
export JAVA_HOME=/usr/lib64/java
export ANDROID_HOME=/a
export ANDROID_PLATFORM=$ANDROID_HOME/platforms/android-23
export ANDROID_BUILD_TOOLS=$ANDROID_HOME/build-tools/28.0.0-rc1
export ANDROID_NDK=$ANDROID_HOME/ndk
export ANDROID_TOOLS=$ANDROID_HOME/tools # sdk tools
PATH=$PATH:$JAVA_HOME/bin:$ANDROID_HOME:$ANDROID_BUILD_TOOLS:$ANDROID_NDK:$ANDROID_TOOLS:$ANDROID_TOOLS/bin:$ANDROID_PLATFORM
Here are my modified commands:
sdkmanager --list
sdkmanager "platforms;android-23"
sdkmanager platform-tools
mkdir /a/prj
cd /a/prj
mkdir --parents src/dom/domain
vi src/dom/domain/SayingHello.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 );
}
}
vi AndroidManifest.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>
If you choose to use the res/
directory instead, adapt the source code and AndroidManifest.xml
as shown below:
# this section is OPTIONAL , the hello world can run without any res
mkdir res/values -p
vi res/values/values.xml
<?xml version='1.0'?>
<resources>
<string name='appLabel'>Saying hello</string>
</resources>
# Reference the resource from the AndroidManifest.xml manifest.
vi AndroidManifest.xml
<!-- <application a:label='Saying hello'> --> <!-- edit this -->
<application a:label='@string/appLabel'>
vi src/dom/domain/SayingHello.java
// v.setText( "Hello world" ); // edit this
v.setText( "This app is called "
+ getResources().getString( R.string.appLabel ));
# end OPTIONAL section
I also created a build script, buildprj
:
#!/bin/bash
#Generate the source for the resource declarations.
aapt package -f \
-I $ANDROID_PLATFORM/android.jar \
-J src -m \
-M AndroidManifest.xml -S res -v
#Compile the source code to Java bytecode (.java ニ .class)
javac \
-bootclasspath $ANDROID_PLATFORM/android.jar \
-classpath src -source 1.7 -target 1.7 \
src/dom/domain/*.java
#Translate the bytecode from Java to Android (.class ニ .dex)
dx --dex --output="classes.dex" src
#Package up the resource files, including the manifest
aapt package -f -F app.apkPart -I $ANDROID_PLATFORM/android.jar \
-M AndroidManifest.xml -S res -v
#Make the full APK using the ApkBuilder tool:
CLASSPATH=$ANDROID_TOOLS/lib/* java \
com.android.sdklib.build.ApkBuilderMain app.apkUnalign \
-d -f classes.dex -v -z app.apkPart
#Optimize the data alignment of the APK (recommended practice https://developer.android.com/studio/command-line/zipalign.html ):
zipalign -f -v 4 app.apkUnalign app.apk
adb install -r app.apk
adb shell am start -n dom.domain/.SayingHello
echo "To uninstall the app: adb uninstall dom.domain"
# cleanup
rm app.apkPart app.apkUnalign classes.dex
find . -name "*.class" -exec rm {} +
find . -name "R.java" -exec rm {} +
To run the build script, just call it:
./buildprj # run the build script
Along the way I ran into some pitfalls:
java -classpath $ANDROID_TOOLS/lib/sdklib.jar \
com.android.sdklib.build.ApkBuilderMain \
app.apkUnalign \
-d -f classes.dex -v -z app.apkPart
it gave an error that didn't say "sdklib.jar doesn't exist/is not found"
Error: Could not find or load main class com.android.sdklib.build.ApkBuilderMain
... :(
cd /a/tools/lib/
ln -s sdklib-25.3.1.jar sdklib.jar
java -classpath $ANDROID_TOOLS/lib/sdklib.jar \
com.android.sdklib.build.ApkBuilderMain \
app.apkUnalign \
-d -f classes.dex -v -z app.apkPart
Exception in thread "main" java.lang.NoClassDefFoundError: com/android/prefs/AndroidLocatio
java -classpath $ANDROID_TOOLS/lib/sdklib.jar \
com.android.sdklib.build.ApkBuilderMain \
app.apkUnalign \
-d -f classes.dex -v -z app.apkPart --help
THIS TOOL IS DEPRECATED. See --help for more information.
Unknown argument: --help
Wow...
Anyway it turns out it 's just explaining 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. UPDATE:Actually it seems impossible to do that from the command line so that warning is a bit strange...
"If --help fails with an ArrayIndexOutOfBoundsException, then instead pass no arguments:
java -classpath SDK/tools/lib/sdklib.jar \
com.android.sdklib.build.ApkBuilderMain
" all right...