Android development is possible without using Gradle. You don't need to depend on it as it is a heavy bloat requires internet connection and downloads a ton of other dependencies, etc. You build faster and know what is going on.

First, you need to install java, in my case, I install the headless version because I don’t use graphics (only command line):
sudo apt-get install openjdk-8-jdk-headless
Then download the last SDK tools of Android
wget https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip
mkdir -p /opt/android-sdk
unzip sdk-tools-linux-3859397.zip -d /opt/android-sdk
Now, we have to install platform tools (which contain ADB), an Android API and build tools. In fact, if you are on Debian, you can avoid installing platform-tools package and only install ADB like that:
sudo apt-get install adb
In this example, I want to compile a simple HelloWorld.
mkdir HelloAndroid
cd HelloAndroid
mkdir -p src/com/example/helloandroid
mkdir obj
mkdir bin
mkdir -p res/layout
mkdir res/values
mkdir res/drawable
mkdir libs
Make the file src/com/example/helloandroid/MainActivity.java and put that inside:
package com.example.helloandroid;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
Make the strings.xml file in the res/values folder. It contains all the text that your application uses:
<resources>
<string name="app_name">A Hello Android</string>
<string name="hello_msg">Hello Android!</string>
<string name="menu_settings">Settings</string>
<string name="title_activity_main">MainActivity</string>
</resources>
The activity_main.xml is a layout file which have to be in res/layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="@string/hello_msg"
tools:context=".MainActivity" />
</RelativeLayout>
You also have to add the file AndroidManifest.xml at the root:
<?xml version='1.0'?>
<manifest xmlns:a='http://schemas.android.com/apk/res/android' package='com.example.helloandroid' a:versionCode='0' a:versionName='0'>
<application a:label='A Hello Android'>
<activity a:name='com.example.helloandroid.MainActivity'>
<intent-filter>
<category a:name='android.intent.category.LAUNCHER'/>
<action a:name='android.intent.action.MAIN'/>
</intent-filter>
</activity>
</application>
</manifest>
Build the code
export PROJ=path/to/HelloAndroid
First, we need generate the R.java file which is necessary for our code:
cd /opt/android-sdk/build-tools/26.0.1/
./aapt package -f -m -J $PROJ/src -M $PROJ/AndroidManifest.xml -S $PROJ/res -I /opt/android-sdk/platforms/android-19/android.jar
-m instructs aapt to create directories under the location specified by -J
-J specifies where the output goes. Saying -J src will create a file like src/com/example/helloandroid/R.java
-S specifies where is the res directory with the drawables, layouts, etc.
-I tells aapt where the android.jar is. You can find yours in a location like android-sdk/platforms/android-
Now, we have to compile the .java files:
cd /path/to/AndroidHello
javac -d obj -classpath src -bootclasspath /opt/android-sdk/platforms/android-19/android.jar src/com/example/helloandroid/*.java
If you have use an external, add it the classpath:
javac -d obj -classpath "src:libs/<your-lib>.jar" -bootclasspath /opt/android-sdk/platforms/android-19/android.jar src/com/example/helloandroid/*.java
The compiled .class files are in obj folder, but Android can’t read them. We have to translate them in a file called “classes.dex” which will be read by the dalvik Android runtime:
cd /opt/android-sdk/build-tools/26.0.1/
./dx --dex --output=$PROJ/bin/classes.dex $PROJ/obj
But if you use external libraries, do rather:
./dx --dex --output=$PROJ/bin/classes.dex $PROJ/*.jar $PROJ/obj
If you have the error UNEXPECTED TOP-LEVEL EXCEPTION, it can be because you use old build tools and DX try to translate java 1.7 rather than 1.8. To solve the problem, you have to specify 1.7 java version in the previous javac command:
cd /path/to/AndroidHello
javac -d obj -source 1.7 -target 1.7 -classpath src -bootclasspath /opt/android-sdk/platforms/android-19/android.jar src/com/example/helloandroid/*.java
The -source option specify the java version of your source files. Note that we can use previous versions of Java even we use OpenJDK 8 (or 1.8).
We can now put everything in an APK:
./aapt package -f -m -F $PROJ/bin/hello.unaligned.apk -M $PROJ/AndroidManifest.xml -S $PROJ/res -I /opt/android-sdk/platforms/android-19/android.jar
cp $PROJ/bin/classes.dex .
./aapt add $PROJ/bin/hello.unaligned.apk classes.dex
Be aware: until now, we used three AAPT commands, the first and the second one are similar but they don’t do the same. You have to copy the classes.dex file at the root of project like above! Otherwise, AAPT won’t put this file at right place in the APK archive (because an APK is like a .zip file). The generated package can’t be installed by Android because it’s unaligned and unsigned. If you want, you can check the content of the package like this:
./aapt list $PROJ/bin/hello.unaligned.apk
Sign the package
keytool -genkeypair -validity 365 -keystore mykey.keystore -keyalg RSA -keysize 2048
Just answer the questions and put a password.
You can sign an APK like this:
./apksigner sign --ks mykey.keystore $PROJ/bin/hello.apk
Align the package
./zipalign -f 4 $PROJ/bin/hello.unaligned.apk $PROJ/bin/hello.apk
Alignment increase the performance of the application and may reduce memory use.
Test the application
adb install $PROJ/bin/hello.apk
adb shell am start -n com.example.helloandroid/.MainActivity
sh script version
#!/bin/bash
set -e
AAPT="/path/to/android-sdk/build-tools/23.0.3/aapt"
DX="/path/to/android-sdk/build-tools/23.0.3/dx"
ZIPALIGN="/path/to/android-sdk/build-tools/23.0.3/zipalign"
APKSIGNER="/path/to/android-sdk/build-tools/26.0.1/apksigner" # /!\ version 26
PLATFORM="/path/to/android-sdk/platforms/android-19/android.jar"
echo "Cleaning..."
rm -rf obj/*
rm -rf src/com/example/helloandroid/R.java
echo "Generating R.java file..."
$AAPT package -f -m -J src -M AndroidManifest.xml -S res -I $PLATFORM
echo "Compiling..."
javac -d obj -classpath src -bootclasspath $PLATFORM -source 1.7 -target 1.7 src/com/example/helloandroid/MainActivity.java
javac -d obj -classpath src -bootclasspath $PLATFORM -source 1.7 -target 1.7 src/com/example/helloandroid/R.java
echo "Translating in Dalvik bytecode..."
$DX --dex --output=classes.dex obj
echo "Making APK..."
$AAPT package -f -m -F bin/hello.unaligned.apk -M AndroidManifest.xml -S res -I $PLATFORM
$AAPT add bin/hello.unaligned.apk classes.dex
echo "Aligning and signing APK..."
$APKSIGNER sign --ks mykey.keystore bin/hello.unaligned.apk
$ZIPALIGN -f 4 bin/hello.unaligned.apk bin/hello.apk
if [ "$1" == "test" ]; then
echo "Launching..."
adb install -r bin/hello.apk
adb shell am start -n com.example.helloandroid/.MainActivity
fi
Step by step guide for Android development
In this guide you will develop an Android application from scratch - without an IDE and also without Gradle.
I have jdk-21.0.7 installed and JAVA_HOME defined, also jdk bin folder added to PATH variable. Gradle downloaded Android command line tools only downloaded. https://developer.android.com/studio/index.html#command-line-tools-only Unzip android command line tools into ANDROID SDK folder. List installed and available packages:
sdkmanager --list [options]
[--channel=channel_id] // Channels: 0 (stable), 1 (beta), 2 (dev), or 3 (canary)
Execute the following to list stable packages:
sdkmanager --list --channel=0
To install packages:
sdkmanager packages [options]
The packages argument is an SDK-style path, as shown with the –list command, wrapped in quotes. For example, “build-tools;34.0.0” or “platforms;android-33”. To install Android SDK Platform 36, Android SDK Build-Tools 36 and Android SDK Platform-Tools
sdkmanager "platforms;android-36" "build-tools;36.0.0" "platform-tools"
SDK folder structure:
Recommended settings for environment: (env variables reference : https://developer.android.com/tools/variables#set)
add the following to PATH
under project/libs folder download
Below is the batch script for manual compilation steps
@echo off
call clean.bat
SET ANDROID_JAR="%ANDROID_HOME%\platforms\android-36\android.jar"
:: build core module
cd core
mkdir build
mkdir build\lib
dir /s /B *.java > sources.txt
call javac -d build -classpath ..\libs\gdx-1.13.1.jar;..\libs\armeabi-v7a.jar @sources.txt
call jar cvf build\lib\core.jar -C build .
::echo "--------------------------------------"
::echo "core compile complete..."
::echo "--------------------------------------"
:: build android module
cd ..\android
mkdir build
mkdir build\gen
mkdir build\compiled-res
mkdir bin
call aapt2 compile --dir res -o build/compiled-res
SET flat_files=
for /f "tokens=* delims=" %%i in ('dir /s /B *.flat') do ( call set "flat_files=%%flat_files%% %%i" )
call aapt2 link -o build/app-unsigned.apk -I %ANDROID_JAR% --manifest AndroidManifest.xml --min-sdk-version 26 --target-sdk-version 36 --version-code 123 --java build\gen --debug-mode %flat_files%
::echo "--------------------------------------"
::echo "aapt2 compile-link complete..."
::echo "--------------------------------------"
dir /s /B *.java > sources.txt
call javac -d bin -classpath %ANDROID_JAR%;..\core\build\lib\core.jar;..\libs\gdx-1.13.1.jar;..\libs\gdx-backend-android-1.13.1.jar;..\libs\armeabi-v7a.jar @sources.txt
::echo "--------------------------------------"
::echo "android compile complete..."
::echo "--------------------------------------"
call jar cvf classes.jar -C bin .
call d8 classes.jar ..\core\build\lib\core.jar ..\libs\*.jar --output bin --lib %ANDROID_JAR% --min-api 26 --debug
::echo "--------------------------------------"
::echo "dex complete..."
::echo "--------------------------------------"
cd bin
call "C:\Program Files\7-Zip\7z.exe" a -tzip ..\build\app-unsigned.apk classes.dex
cd..
call "C:\Program Files\7-Zip\7z.exe" a -tzip build\app-unsigned.apk lib
::echo "--------------------------------------"
::echo "added .so files to apk..."
::echo "--------------------------------------"
call zipalign -f 4 build\app-unsigned.apk build\aligned.apk
::call zipalign -P 16 -f -v 4 build\app-unsigned.apk build\aligned.apk
::call zipalign -c -P 16 -v 4 build\aligned.apk
call apksigner sign --ks ToyKey.keystore --ks-key-alias HelloJNIKey --ks-pass pass:armena --out build\final.apk build\aligned.apk
::echo "--------------------------------------"
::echo "apk sign complete..."
::echo "--------------------------------------"
call adb install -r build\final.apk
cd..
to generate key
%JAVABIN%\keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000
install emulator:
sdkmanager "emulator"
find a system image using the following command:
sdkmanager.bat --list
install system image:
sdkmanager.bat "system-images;android-30;google_apis_playstore;x86_64"
list available devices with their ids:
avdmanager.bat list device
create device with name test and device id 39 using the system image we installed above:
avdmanager create avd -n test -k "system-images;android-30;google_apis_playstore;x86_64" -d 39
run the newly created device using emulator tool:
emulator @test -skin 768x1280
Installation is done via adb command to specific devices..
adb install <path/to/your/app.apk>
Lists all Android Virtual Devices (AVDs) available on your development machine. This command is useful for identifying the emulators you can launch to test your application.
emulator -list-avds
Start a specific Android Virtual Device (AVD).
emulator -avd avd_name
This command saves the logcat output to logcat.txt in the current directory. The d option dumps the current logcat buffer.
adb logcat -d > logcat.txt
Use adb qualified names of all apps/packages. If you forget what your qualified app name, but it’s installed on the device, then:
adb shell pm list packages
And then
adb shell monkey -p your.app.name -v 1
(to be more precise, this runs the app and sends 1 random input to it)
So it is possible to develop an Android application just by using the command line without any need for an IDE. This enables a much more comprehensive learning process.