Développer une app android sans Android Studio
Je suis un mec bizarre, j'ai envie de développer une application Android sans Android Studio. La vrai raison, c'est que lancer une IDE auquel je n'ai pas envie de m'habituer juste pour un type de développement, alors que je me sens bien dans mon flow de dev sur Emacs, ne m'enchante guère ; et comme j'aime bien me rajouter des challenges inutiles, c'est parfait.
Installation de l'environnement
La première étape est d'installer tous les élements nécéssaires à la compilation et au linkage des programmes ainsi que les outils pour tester et déboguer.
Archi i386
L'OS Android se base sur une architecture i386. Comme nos ordinateurs, sur lesquels on va développer, sont maintenant en x86 64bits, il va falloir faire une compilation croisée depuis l'architecture hôte vers l'architecture cible i386. On doit donc installer l'ABI i386 de Linux. J'ai parlé d'i386 ? i386.
sudo dpkg --add-architecture i386 sudo apt update sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386 lib32z1 libbz2-1.0:i386
JDK Java
Les applications Android sont codées en Java. Il faut donc installer le JDK de Java.
apt install default-jdk
SDK Android
Il faut installer le SDK d'Android, à télécharger depuis le site web : https://developer.android.com/studio, descendez un peu pour trouver le lien de téléchargement contenant uniquement le SDK. Désarchivez l'archive.
Dedans on retrouve des outils, de bêtes scripts shells, permettant de gérer les SDK : les télécharger, les mettre à jour, etc..
Il y a un problème cependant ils ne fonctionnent pas avec un JDK > v8. C'est cocasse puisque le standard actuel est le 10.
Il faut corriger les outils, en l'éditant, et remplacer :
DEFAULT_JVM_OPTS='"-Dcom.android.sdklib.toolsdir=$APP_HOME"'
Par :
DEFAULT_JVM_OPTS='"-Dcom.android.sdklib.toolsdir=$APP_HOME" -XX:+IgnoreUnrecognizedVMOptions --add-modules java.se.ee'
Ou on peut aussi décider d'utiliser le JDK 8 en downgradant le paquet.
Installation des images et outils de builds
Il faut utiliser l'outil sdkmanager patché (cf point du haut) pour installer une image (l'iso de la machine virtuelle de développement Androd) et les outils de builds de l'application :
./bin/sdkmanager "build-tools;26.0.0" "platforms;android-26" "system-images;android-26;google_apis;x86_64"
Création d'une AVD
Une Android Virtual Device est une machine virtuelle permettant de simuler android pour tester son application.
Pour un créer un :
~/AndroidSDK/bin/avdmanager create avd --force --name testAVD --abi google_apis/x86_64 --package 'system-images;android-26;google_apis;x86_64'
On peut lister les AVD existant :
~/AndroidSDK/bin/avdmanager list device
On utilise l'option -d pour choisir le device a émuler.
S'il répond 'null' c'est qu'il ne trouve pas l'image, vérifier qu'elle est bien installée.
Puis on utilise emulator pour lancer la VM :
./emulator -list-avds ./emulator -avd testAVD
Il faut être dans le répertoire pour le faire, l'outil utilise des liens direct.
Compiler un APK
Maintenant qu'on a les outils de compilation et de test, on va pouvoir passer à la compilation d'un APK.
Structure
Tel quel
main/
- java/com/example/nimag42/testapp/activite.java:
package com.example.nimag42.testapp; import android.app.Activity; import android.os.Bundle; import android.widget.TextView; public class activite extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TextView text = new TextView(this); text.setText("Bonjour, vous me devez 1 000 000€."); setContentView(text); } }
- AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.nimag42.testapp"> <application android:allowBackup="true" android:label="lol" android:supportsRtl="true"> <activity android:name="com.example.nimag42.testapp.activite"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
Compilation
- 1. Générer le code java des ressources :
$ANDROID_HOME/build-tools/$android-version/aapt package -f -m -J $PROJ/src -M $PROJ/AndroidManifest.xml -S $PROJ/res -I $ANDROID_HOME/platforms/android-19/android.jar
Ça va générer un fichier R.java dans le src/com…/…// pour les ressources.
- 2. Compiler les .java
javac -d obj -classpath "src:libs/other.jar" -bootclasspath $ANDROID_HOME/platforms/android-19/android.jar src/com/example/.../*.java
Ça va générer dans .class dans le obj/
- 3. Transpiler les .class en .dex (pour la VM dalvik d'android)
$ANDROID_HOME/build-tools/$android-version/dx --dex --output=$PROJ/bin/classes.dex $PROJ/obj
- 4. Construire le paquet APK
$ANDROID_HOME/build-tools/$android-version/aapt package -f -m -F $PROJ/bin/hello.apk -M $PROJ/AndroidManifest.xml -S $PROJ/res -I $ANDROID_HOME/platforms/android-19/android.jar $ANDROID_HOME/build-tools/$android-version/aapt add $PROJ/bin/hello.apk $PROJ/bin/classes.dex
- 5. optionellement on peut utiliser aapt pour confirmer le paquet :
aapt list
- 6. Signer l'apk
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my-release-key.keystore my_application.apk alias_name
- 7. Optionnel aligner l'apk. Cela permet de minimiser l'empreinte de l'APK.
Tester
Pour tester, il faut lancer une VM avd.
Puis dans un second terminal, on utilise adb pour installer l'apk sur l'avd :
$ANDROID_HOME/platform-tools/adb install -r hello.apk
Le -r permet de réinstaller
Conclusion et sources
C'est compliqué, mais ça se fait, et si ça me permet d'éviter de lancer un IDE codé avec le cul et d'être un frimeur à compiler des apps Android uniquement avec mon terminal et mon Emacs, objectif atteint !
Je me suis inspiré de cet article : https://medium.com/@authmane512/how-to-build-an-apk-from-command-line-without-ide-7260e1e22676
J'ai suivi ce thread SO pour la signature du paquet : https://stackoverflow.com/questions/10930331/how-to-sign-an-already-compiled-apk