the 2016 android developer toolbox [devoxx]
TRANSCRIPT
#DevoxxFR
La boîte à outils du développeur Android de 2016
Gautier Mechling @Nilhcem
1
#DevoxxFR
Présentation
2
@Nilhcem
Gautier Mechling
Développeur passionnné
#DevoxxFR
happn
3
"Retrouvez qui vous croisez"
Cette vidéo est une oeuvre de pure fiction. Toute ressemblance avec des situations réelles ou des personnes existantes ne saurait être que carrément fortuite, ma gueule.
#DevoxxFR 4
Parlons de…
#DevoxxFR
La boîte à outils du développeur Android de 2016
Gautier Mechling @Nilhcem
5
#DevoxxFR
L’explication
6
#DevoxxFR
L’explication
7
“Quel homme !"
“Grand et fort !”
“Retenez moi,je vais m'évanouir"
“Si beau ! il ferait pas partie du JUG par hasard ?"
#DevoxxFR
L’explication
8
“Bon c’est chaud là…”
“Pas de tests ? Même pas 1 ou 2 qui échouent ?"
“Retenez moi,je vais m'évanouir"
“Comment ils ont pu concevoir ÇA ?”
“Use the right tools for the right job"
(comme ils disent les américains)
YOLO
#DevoxxFR
Gradle
12
(Avec le plugin Android)
#DevoxxFR
Build Variants
13
#DevoxxFR
Application de Debug
16
• Afficher les informations de build
• Changer de serveur à la volée
• Afficher les logs
• Envoyer des rapports de bugs
• etc.
#DevoxxFR
L'application DevoxxFR
17
https://github.com/Nilhcem/devoxxfr-2016
#DevoxxFR
Mesurer
18
#DevoxxFR
Android Studio 2.0
Onglet : Android Monitor
19
#DevoxxFR 20
#DevoxxFR
Détecter les fuites mémoire
21
#DevoxxFR 22
#DevoxxFR
Leak Canary
23
https://www.github.com/square/leakcanary
#DevoxxFR
Takthttps://github.com/wasabeef/Takt
compile 'jp.wasabeef:takt:1.0.2'
public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); Takt.stock(this).play(); }}
24
#DevoxxFR
Hugo
25
https://www.github.com/JakeWharton/hugo
Préfixer les classes / methodes avec:@DebugLog
Résultat :DevoxxApp V ⇢ onCreate() V ⇢ initGraph() V ⇠ initGraph [13ms] V ⇢ initLogger() V ⇠ initLogger [1ms] V ⇠ onCreate [73ms]
#DevoxxFR
Pidcat
26
https://github.com/JakeWharton/pidcat
$ pidcat com.nilhcem.devoxxfr
#DevoxxFR
AndroidDevMetricshttps://github.com/frogermcs/AndroidDevMetrics
apply plugin: 'com.frogermcs.androiddevmetrics'
public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); AndroidDevMetrics.initWith(this); }}
27
#DevoxxFR
Outils d’analyse statique de code
28
#DevoxxFR
Analyse statique
29
- Lint
- PMD
- Checkstyle
- Findbugs
- Infer
#DevoxxFR
SonarQube
30
#DevoxxFR
Dockerfile SonarQube
31
FROM java:8MAINTAINER Nilhcem
RUN DEBIAN_FRONTEND=noninteractive apt updateRUN DEBIAN_FRONTEND=noninteractive apt install -y wget unzipRUN wget -q https://sonarsource.bintray.com/Distribution/sonarqube/sonarqube-5.4.zipRUN unzip -qq sonarqube-5.4.zip -d /opt/RUN rm sonarqube-5.4.zip
EXPOSE 9000CMD ["/opt/sonarqube-5.4/bin/linux-x86-64/sonar.sh", “console"]
Ensuite lancer :
$ docker build -t nilhcem/sonarqube . $ docker run -p 9000:9000 -d nilhcem/sonarqube
#DevoxxFR
SonarQube : Configuration Gradle
32
apply plugin: 'org.sonarqube'
sonarqube { properties { def appProject = project(':app') def appProjectBuildDir = appProject.buildDir
property 'sonar.projectKey', 'devoxxfr' property 'sonar.projectName', 'DevoxxFR 2016' property 'sonar.projectVersion', appProject.android.defaultConfig.versionName
property 'sonar.host.url', 'http://docker:9000' property 'sonar.sources', 'src' property 'sonar.sourceEncoding', 'UTF-8' property 'sonar.java.binaries', 'build'
property 'sonar.exclusions', '**/*Test.java' property 'sonar.core.codeCoveragePlugin', 'jacoco' property 'sonar.jacoco.reportPath', "$appProjectBuildDir/jacoco/testProductionDebugUnitTest.exec" property 'sonar.junit.reportsPath', "$appProjectBuildDir/test-results/productionDebug" }}$ gradlew :app:assembleProductionDebug :app:testProductionDebugUnitTest :app:sonarqube
#DevoxxFR 33
#DevoxxFR 34
#DevoxxFR
Tester
35
#DevoxxFR
Mock Server
36
#DevoxxFR
NodeJS + Express
37
/* Initialisation */ var fs = require('fs'); var express = require('express'); var app = express();app.set('port', process.env.PORT || 8080); var port = app.get('port');
/* Service web : liste des speakers */app.get('/speakers', function(req, res) { res.type('application/json; charset=utf8'); res.status(200).send(fs.readFileSync('data/speakers.json', 'utf8')); });
/* Autres services à mocker */// ...
/* Démarrage du serveur */app.listen(port, function () { console.log('Express server listening on port ' + port); });
#DevoxxFR
Simuler une réponse lente
38
sleep(2000);
function sleep(durationMillis) { var now = new Date().getTime(); while(new Date().getTime() < now + durationMillis) { // do nothing }}// SVP ne prenez pas ce slide en photo, j’en suis pas fier
#DevoxxFR
Exemple
https://github.com/Nilhcem/devoxxfr-2016/tree/master/mockserver
$ npm install $ node server.js
Ensuite, aller sur http://localhost:8990/
39
#DevoxxFR
Hosts Editor
40
#DevoxxFR
Débugueur HTTP
41
#DevoxxFR
Web Debugging Proxies
42
- mitmproxy
- Fiddler
- Charles proxy
#DevoxxFR
Charles Proxy
43
• Simuler une connexion lente/instable
• Répéter des requêtes
• Vérifier les réponses
• Ajouter des points d’arrêt pour :
• Annuler un appel HTTP(s)
• Éditer une requête
• Éditer une réponse
#DevoxxFR
Annuler une requête
44
#DevoxxFR
Éditer une réponse
45
#DevoxxFR
Analyser
46
#DevoxxFR
Options développeurs
47
#DevoxxFR
Afficher les contours
48
#DevoxxFR
Conflits GPU (overdraw)
49
#DevoxxFR
hierarchyviewer
50
https://developer.android.com/tools/performance/hierarchy-viewer/setup.html#hvproto-variable http://developer.android.com/tools/debugging/debugging-ui.html
$ export ANDROID_HVPROTO=ddm $ exec ${ANDROID_HOME}/tools/monitor
#DevoxxFR
uiautomatorviewer
51
#DevoxxFR
Animations
52
#DevoxxFR
Animations
Faire un screencast :$ adb shell screenrecord /sdcard/demo.mp4 $ adb pull /sdcard/demo.mp4
VLC :Appuyer sur la touche E du clavier pour voir les frames une par une
53
#DevoxxFR
apktool + dex2jar + JD-GUI
54
http://ibotpeaches.github.io/Apktoolhttps://github.com/pxb1988/dex2jarhttp://jd.benow.ca
#DevoxxFR
Stetho
56
#DevoxxFR
Stetho - UI
57
#DevoxxFR
Stetho - Réseau
58
#DevoxxFR
Stetho - Ressources
59
#DevoxxFR
Stetho - Dumpapp
60
#DevoxxFR
Stetho - Dumpapp
61
#DevoxxFR
Stetho - Dumpapp
62
#DevoxxFR
D’autres exemples avec dumpapp
63
#DevoxxFR
Autres exemples dumpapp
64
$ dumpapp accessToken invalidate
$ dumpapp accessToken show fce1235425dcdeadbeef8cafebabe42
$ dumpapp clipboard get Hello
$ dumpapp clipboard set "Text to copy" $ dumpapp onTrimMemory $ dumpapp openIntent scheme://open/speaker/3
$ dumpapp gcmToken uHyMKnEQ:APA91bEHZ6afFLQQMzKgSDjp5y_0397usitPqj_Bp02
$ dumpapp geolocData Location[fused 22.5430883,114.1043205 acc=21 et=+21m5s492ms]
$ dumpapp runningServices com.example.LocationService
#DevoxxFR 65
http://code.tutsplus.com/tutorials/debugging-android-apps-with-facebooks-stetho--cms-24205
class AppDumperPlugin implements DumperPlugin { @Override public String getName() { return "my_plugin_name"; }
@Override public void dump(DumperContext dumpContext) throws DumpException { PrintStream writer = dumperContext.getStdout(); String commandName = (args.isEmpty()) ? "" : args.remove(0);
if (commandName.equals("test")) { out.println("Hello, World!"); } }}
Dumpapp - Création d’un plugin
#DevoxxFR 66
Dumpapp - Création d’un plugin
#DevoxxFR 67
ActivityProvider dans un graph de dépendance en debug
@Singleton public class ActivityProvider implements Application.ActivityLifecycleCallbacks { private Activity currentActivity;
@Inject public ActivityProvider(Application app) { app.registerActivityLifecycleCallbacks(this); }
public Activity getCurrentActivity() { return currentActivity; }
@Override public void onActivityResumed(Activity activity) { currentActivity = activity; }
@Override public void onActivityPaused(Activity activity) { currentActivity = null; } }
Dumpapp - Création d’un plugin
#DevoxxFR
Dumpapp - Création d’un plugin
68
AppDumperPlugin.java:
private void displayCurrentSessionData(PrintStream writer) { Activity activity = activityProvider.getCurrentActivity(); if (activity instanceof SessionDetailsActivity) { try { // Use reflection to access private "session" field Field field = SessionDetailsActivity.class.getDeclaredField("session"); field.setAccessible(true); Session session = (Session) field.get(activity); writer.println(new GsonBuilder().setPrettyPrinting().create().toJson(session)); } catch (Exception e) { writer.println(e.getMessage()); } }}
#DevoxxFR
Stetho - Console + Rhino
69
#DevoxxFR
Ah oui, il y a aussi tous ces autres outils que je voulais présenter mais je crois qu’en fait, il nous
reste plus vraiment trop de temps et c’est bien dommage parce
qu’ils sont aussi importants et puis
70
#DevoxxFR 71
# Ouvrir un deep link adb shell am start -a android.intent.action.VIEW -d "scheme://app/deep/linking"
# Lister les services qui tournent actuellement sur l'appareil adb shell dumpsys activity services
# Récupérer le chemin de l’apk d’une application installée adb shell pm path app.package.name
# Supprimer les données de l'app adb shell pm clean app.package.name
# Prendre un screenshot adb shell screencap -p | perl -pe '\''s/\x0D\x0A/\x0A/g'\'' > screen.png
# Coller le texte du clipboard de son ordi vers son appareil android pbpaste | sed "s/%/%%/g" | sed "s/ /\%\s/g" | xargs adb shell input text
ADB + Shell
#DevoxxFR
Lockito
73
#DevoxxFR
Fill RAM
74
https://play.google.com/store/apps/details?id=com.tspoon.androidtoolbelt
#DevoxxFR
MethodsCount
75
http://www.methodscount.com/https://github.com/mihaip/dex-method-counts
#DevoxxFR
Vysor
76
http://www.vysor.io/
#DevoxxFR
En conclusion
77
#DevoxxFR
Choisir selon vos besoins et préférences
78
#DevoxxFR
La boîte à outils du développeur Android de 2016
Gautier Mechling @Nilhcem
79
#DevoxxFR
La boîte à outils du développeur Android de 2016
Gautier Mechling @Nilhcem
80
NUL
#DevoxxFR
Exempled’une boîte à outils pour Android
Gautier Mechling @Nilhcem
81
#DevoxxFR
Merci
https://twitter.com/Nilhcem https://github.com/Nilhcem/devoxxfr-2016
http://www.slideshare.net/Nilhcem/the-2016-android-developer-toolbox-devoxx
82