2025-08-22
These instructions are written from my experience trying to figure out how to do this (it wasn't easy with Google trying to shove AS, Kotlin and Compose down everyone's throat). This will be written for Linux systems targeting Android 16 (API 36), but if you want to do this on Windows or some other OS, if you're on this page you can probably find a way to adapt these instructions, I believe in you :) I will be omitting the full path to some of the files we create, you should know where you're creating them so it shouldn't be a problem when invoking the commands to write the path to them...
I recommend downloading cmdline-tools from the Android SDK link and using
sdkmanagerthat's part of it to download/update the rest. Make a folder where you'll install the Android SDK, whether in /opt or somewhere in home, I just used
~/android-sdk/and set
$ANDROID_HOMEenvironment variable to that directory. Use the official install instructions so I don't repeat easily accessible stuff. Since I'm building for Android 16, I do
sdkmanager "buildtools;36.0.0" "platforms;android-36"and you can see avaliable options with
sdkmanager --listif you want additional stuff like NDK etc.
Now that we have the tools, time to set up the project directory structure. Without the build tools and resources/assets like icons, it's actually pretty simple. For clarity's sake I will divide the files into multiple folders but some of them are optional, just so it looks cleaner and for future familiarity. Here's the directory tree:
app/ - src/ - main/ - AndroidManifest.xml - java/ - com/ - example/ - helloworld/ - MainActivity.java
Here's AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.helloworld" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="36" /> <application android:allowBackup="true" android:supportsRtl="true"> <activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
Change the minSdkVersion and targetSdkVersion to desired values (if you don't know what to put, 21 for min and latest API level for target are generally good, or something like latest-7 for min). Now for MainActivity.java:
package com.dax.hello; import android.app.Activity; import android.os.Bundle; import android.widget.LinearLayout; import android.widget.TextView; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); LinearLayout layout = new LinearLayout(this); layout.setOrientation(LinearLayout.VERTICAL); TextView textView = new TextView(this); textView.setText("Hello world!"); layout.addView(textView); setContentView(layout); } }
And that's all the files! All that's left is to make an apk out of them, which is actually the most work and kinda tedious without a build system but oh well, I wanted to learn this mostly for educational purposes.
Before we continue, if you don't have a key for signing the apk, we're going to make it now.
keytool -genkey -v -keystore /path/to/tutorialkey.keystore -alias tutorialkey -storetype "JKS" -keyalg RSA -keysize 2048 -validity 10000You can answer the questions with what ever, it doesn't really matter for our purpose.
Next we compile the .java file we wrote with javac:
javac -cp $ANDROID_HOME/platforms/android-36/android.jar MainActivity.javaand remember to change "android-36" to whatever version you're using. Next, translate the resulting .class file to .dex with d8 from the build-tools:
d8 MainActivity.class --lib $ANDROID_HOME/platforms/android-36/android.jar --output classes.dexand again, change 36 to whatever you're using. Now onto forming the apk, pay attention if I'm using aapt or aapt2 since they're different:
aapt2 link --manifest AndroidManifest.xml -o helloworld_unaligned.apk -v -I $ANDROID_HOME/platforms/android-36/android.jar aapt a -v helloworld_unaligned.apk classes.dex zipalign -P 16 -f -v 4 helloworld_unaligned.apk helloworld.apk apksigner sign --ks /path/to/your/key.keystore helloworld.apk
Congratulations! Hopefully you have a working apk now. You can try it out on a real device or on an emulator, I don't be going into how to do that here though since it should be simple enough to figure out ;)
This hello world program is really barebones, we haven't dealt with the app name and icon (basic resources) and because of that haven't dealt with asset compilation with "aapt2 compile" and R.java, the directories and files associated with the resources and changes to the AndroidManifest.xml file. We have also done the View layout programmatically instead of declaratively (making an .xml file), which is frowned upon in current times (though it has it's benefits). If you're having trouble getting it to work, try the lint tool included in cmdline-tools. You can also inspect your apk with other tools we downloaded like apkanalyzer and aapt2 dump. You can also unzip the apk since apks are basically zip files. You should have 3 files inside, the AndroidManifest.xml, classes.dex and resources.arsc.