image/svg+xml $ $ ing$ ing$ ces$ ces$ Res Res ea ea Res->ea ou ou Res->ou r r ea->r ch ch ea->ch r->ces$ r->ch ch->$ ch->ing$ T T T->ea ou->r

Nous décrivons ici quelques astuces qui pourraient être utiles pour les TPs et projets sous Android.

Utiliser rapidement les commandes du SDK (sous Linux)

L'utilisation des outils du SDK en ligne de commande peut être utile (adb, emulator, monitor, lint...). Pour y accéder rapidement, ajoutez dans la variable d'environnement PATH le chemin vers les répertoires contenant ces programmes :

export ANDROID_SDK=/chemin/vers/le/sdk # à remplacer par le chemin vers le SDK
export PATH=$PATH:$ANDROID_SDK/tools:$ANDROID_SDK/platform-tools

Si vous ne connaissez pas le chemin vers le SDK, recherchez par exemple le répertoire platform-tools sur le système de fichiers (ce qui peut prendre un certain temps) :

find / -name "platform-tools"

Rajoutez les commandes EXPORT dans le fichier ~/.bashrc pour éviter d'avoir à les retaper à chaque ouverture de shell.

Testez la commande adb devices pour vérifier si adb est bien appelé et affiche tous les appareils connectés.

Accélérer la compilation en écrivant les fichiers compilés en RAM

La compilation d'un projet Android est une procédure complexe gérée par Gradle : l'usage de nombreux outils est mis en œuvre. Il est toujours préférable d'écrire les fichiers compilés sur un support rapide. En particulier, l'utilisation d'un serveur de fichiers distant (de type NFS ou Samba) est à proscrire. L'expérience montre aussi que des soucis de verrouillage de fichiers peuvent survenir rendant certains répertoires créés insupprimables de façon transitoire.

Il est donc conseillé de compiler son projet dans un répertoire en RAM ; c'est généralement le cas du répertoire /tmp qui utilise tmps (système de fichier en RAM). Pour compiler dans /tmp, on modifiera le fichier build.gradle du projet pour y spécifier le répertoire de compilation :

allprojects {
	...
    buildDir = "/tmp/${rootProject.name}/${project.name}"
    ...
}

Créer des bibliothèques Android

Si votre projet est très très volumineux, le découpage du code de façon modulaire en bibliothèques peut être judicieux. Ainsi, le changement de code dans une bibliothèque donnée réduit les tâches de recompilation pour le projet entier.

Utiliser des bibliothèques Java/Android publiées sur Github

L'utilisation de dépendances nécessite de les déclarer dans le fichier build.gradle de l'application (section dependencies). Les bibliothèques utilisées doivent être publiées sur un dépôt Maven déclaré dans la section repositories. Si la bibliothèque est disponible sur GitHub, il est possible d'utiliser JitPack qui mavenise un dépôt GitHub. La façon de procéder (très simple) est indiquée sur la page de JitPack.

Utiliser Instant Run

Instant Run est une fonctionnalité disponible depuis Android 5 permettant la mise à jour rapide d'une application active en cours de test sur l'appareil. Ainsi par exemple, si l'on modifie une méthode, seul le code compilé de cette méthode est envoyé sur l'appareil et l'application est patchée en cours de fonctionnement. Cependant certaines modifications nécessitent la réinstallation complète de l'application comme le changement de manifeste.

L'utilisation de l'Instant Run nécessite l'installation d'un plugin. Il est possible que cette installation ne soit pas possible sur les machines de l'université (nécessité d'avoir des droits en écriture sur le répertoire d'installation d'Android).

Problèmes de compatibilité de bibliothèques

Les problèmes de compatibilité de bibliothèques sont des soucis courants lors de la compilation de projets Android. Les bibliothèques utilisées sont indiquées dans la section dependencies du fichier build.gradle dont voici un exemple :

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation"org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    implementation 'com.android.support:appcompat-v7:26.1.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

On remarquera que l'on indique toujours la version de la bibliothèque utilisée. La bibliothèque est recherchée automatiquement sur les dépôts spécifiés dans build.gradle. Nous avons généralement par défaut :

allprojects {
    repositories {
        google()
        jcenter()
    }
}

Cela nous permet d'utiliser le dépôt officiel de Google ainsi que jcenter, un dépôt populaire de paquetages Maven.

Avec la précédente déclaration de dépendances, nous obtenons l'erreur suivante :

Error:Execution failed for task ':app:preDebugAndroidTestBuild'.
> Conflict with dependency 'com.android.support:support-annotations' in project ':app'. Resolved versions for app (26.1.0) and test app (27.1.1) differ. See https://d.android.com/r/tools/test-apk-dependency-conflicts.html for details.

La dépendance en conflit est une dépendance transitive de plusieurs dépendances de la section dependencies. En exécutant la commande ./gradlew app:dependencies dans le répertoire du projet, on visualise tous les arbres de dépendances pour chaque tâche. On constate pour la tâche debugAndroidTestRuntimeClasspath que :

La solution sera ici d'utiliser une version plus récente de appcompat, ici com.android.support:appcompat-v7:27.1.1 : on modifie le build.gradle en conséquence.

Problèmes divers de compilation insolubles et bugs divers

Pour tout problème de compilation difficilement résolvable à la main concernant un projet utilisant une configuration de compilation a priori, une solution consiste à repartir d'un nouveau projet créé avec Android Studio dans lequel on déplace les sources de l'ancien projet (bien sûr sans les fichiers build.gradle, nous utiliserons ceux du nouveau projet a priori moins sources de problèmes a priori).

Android Studio peut se comporter bizarrement lorsque l'on ouvre un projet par un chemin comprenant un lien symbolique ; il est préférable d'utiliser le chemin réel.

Compilation plus rapide en mode offline

Gradle communique en permanence avec des dépôts de paquetages pour vérifier si de nouvelles versions sont disponibles. Pour accélérer la compilation, on pourra activer le mode offline. Dans le dialogue de paramétrage File>Settings, recherchez la section gradle puis cochez la case Offline work. Il est nécessaire bien sûr que toutes les dépendances soient déjà disponibles dans le cache de Gradle (sinon Gradle ne pourra compiler).