How to make Android apps without IDE from command line
A HelloWorld without Android Studio
Update: I’ve made a new course that explain how you can avoid Android Studio and Gradle, but still use IntelliJ iDE:
Hello everybody!
In this tutorial, I will show you how you can build/compile an APK (an Android app) from your java code using terminal (on Linux) without IDE or in other words without Android Studio. At the end, I will also show you a script to automate the process. In this example, I will use Android API 19 (4.4 Kitkat) to make a simple HelloWorld. I want to say that I will do this tutorial without android command which is deprecated.
1. Install Java
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
2. Install all SDK tools
Then download the last SDK tools of Android which you can find here:
Or simply do:
wget https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip
I recommend to unzip it in the /opt directory inside another directory that we will call “android-sdk”:
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
3. Code the application
In this example, I want to compile a simple HelloWorld. So, first, we need to make a project directory:
mkdir HelloAndroid
cd HelloAndroid
Then we have to make the files tree:
mkdir -p src/com/example/helloandroid
mkdir obj
mkdir bin
mkdir -p res/layout
mkdir res/values
mkdir res/drawable
If you use exernal libraries (.jar files), also make a folder for them:
mkdir libs
You have an example here:
Make the file src/com/example/helloandroid/MainActivity.java and put that inside:
Make the strings.xml file in the res/values folder. It contains all the text that your application uses:
The activity_main.xml is a layout file which have to be in res/layout:
You also have to add the file AndroidManifest.xml at the root:
4. Build the code
Now, I recommend to store the project path in a variable:
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-<API level>/android.jar
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
5. Sign the package
To do so, we firstly create a new keystore with the command keytool given by Java:
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
Note that apksigner only exist since Build Tools 24.0.3.
6. Align the package
It’s as simple as that:
./zipalign -f 4 $PROJ/bin/hello.unaligned.apk $PROJ/bin/hello.apk
Alignment increase the performance of the application and may reduce memory use.
7. Test the application
To test the application, connect your smartphone with a USB cable and use ADB:
adb install $PROJ/bin/hello.apk
adb shell am start -n com.example.helloandroid/.MainActivity
But before run this command, I recommend to run this one:
adb logcat
If there is an error during installation or running, you see it with that command.
Voila! Here’s the result:
8. Make a script
If you don’t want to run all these steps every time you would like to compile your app, make a script! Here’s mine:
To use it, run:
cd /path/to/AndroidHello
./build.sh test
Notes
- You can remove “test” if you just want to compile without testing.
- This script only compile and run the app on the phone. But I can also make a script to automatically generate a new project like this one. I think I have a good idea to do so, but I need to know if you are interested. If it’s the case, please leave a comment or send me an e-mail.
- I can also complete the script for external libraries. Likewise, let me know if you want this.
If you have any questions, don’t hesitate to ask them below or by e-mail ;-)! EDIT: Well I’m very busy actually…