Download - The 2015 Android Developer Toolbox
The 2015 Android Developer Toolbox
#droidconpl2015
@Nilhcem
Gau$er Mechling
Android So)ware Cra)sman
#droidconpl2015
happnFind the people you've crossed paths with.
#droidconpl2015
?#droidconpl2015
#droidconpl2015
"Use the right tool for the right job"
#droidconpl2015
#droidconpl2015
#droidconpl2015
Measuring
Tes$ng
Analyzing
#droidconpl2015
MeasuringTes$ng
Analyzing
#droidconpl2015
Measuring• You do not Op+mize without measuring.
#droidconpl2015
Measuring
• The first rule of Op0miza0on Club is, you do not Op0mize1
1 h$p://www.perlmonks.org/?node_id=962631
#droidconpl2015
Android Studio(Android Monitor tab)
#droidconpl2015
Memory analysis
#droidconpl2015
Android Studio
#droidconpl2015
Frame Rateh"ps://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(); }}
#droidconpl2015
Hugoh"ps://github.com/JakeWharton/hugo
Prefix classes/methods with:
@DebugLog
Result:
BBLApplication V ⇢ onCreate()
V ⇢ initLogger()
V ⇠ initLogger [1ms]
V ⇢ initGraph()
V ⇠ initGraph [16ms]
V ⇠ onCreate [71ms]
#droidconpl2015
Pidcath"ps://github.com/JakeWharton/pidcat
$ pidcat pl.droidcon.app
#droidconpl2015
#PerfMa(ers#droidconpl2015
#PerfMa(ersactually...
#droidconpl2015
#QualityMa*ers
#droidconpl2015
Code sta)c analysis tools
#droidconpl2015
Code sta)c analysis tools• Lint
• PMD
• Checkstyle
• Findbugs
• Facebook's infer
#droidconpl2015
SonarQube
#droidconpl2015
#droidconpl2015
#droidconpl2015
#droidconpl2015
Dockerfile
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.2.zipRUN unzip -qq sonarqube-5.2.zip -d /opt/RUN rm sonarqube-5.2.zip
EXPOSE 9000EXPOSE 9092
CMD ["/opt/sonarqube-5.2/bin/linux-x86-64/sonar.sh", "console"]
#droidconpl2015
Gradle
apply plugin: 'org.sonarqube'
sonarqube { properties { def appProject = project(':app') def appProjectDir = appProject.projectDir def appProjectBuildDir = appProject.buildDir
property 'sonar.projectKey', 'my-app' property 'sonar.projectName', 'Android app' property 'sonar.projectVersion', appProject.android.defaultConfig.versionName
property 'sonar.host.url', 'http://docker:9000' property 'sonar.jdbc.url', 'jdbc:h2:tcp://docker:9092/sonar' property 'sonar.jdbc.username', 'sonar' property 'sonar.jdbc.password', 'sonar'
property 'sonar.sources', 'src' property 'sonar.sourceEncoding', 'UTF-8' property 'sonar.java.binaries', 'build'
property 'sonar.core.codeCoveragePlugin', 'jacoco' property 'sonar.junit.reportsPath', "$appProjectBuildDir/test-results/prodDebug" property 'sonar.jacoco.reportPath', "$appProjectBuildDir/jacoco/testProdDebugUnitTest.exec" }}
./gradlew :app:assembleProdDebug :app:testProdDebug :app:sonarqube
#droidconpl2015
Measuring
Tes$ngAnalyzing
#droidconpl2015
Mock Server
#droidconpl2015
NodeJS + Express/* Setup */var fs = require('fs');var express = require('express');var app = express();app.set('port', process.env.PORT || 8080);var port = app.get('port');
/* User web service */app.get('/api/users', function(req, res) { res.type('application/json; charset=utf8'); res.status(200).send(fs.readFileSync('data/users.json', 'utf8'));});
/* Other web services */// ...
/* Starting the server */app.listen(port, function () { console.log('Express server listening on port ' + port);});
#droidconpl2015
Examples
h"ps://github.com/Nilhcem/droidcon-2015-mobile-app/tree/toolbox/mockserver
or
h"ps://github.com/Nilhcem/xebia-android-hp/tree/master/mockserver$ npm install$ node server.js
Then, go to http://localhost:$PORT/#droidconpl2015
Gradle configura.onproductFlavors { production { buildConfigField 'String', 'WS_ENDPOINT', '"http://www.your_server.com/"' }
mock { buildConfigField 'String', 'WS_ENDPOINT', '"http://${mock_server_ip}:${mock_server_port}/"' }}
#droidconpl2015
Hosts Editor
h"ps://play.google.com/store/apps/details?id=com.nilhcem.hostseditor
#droidconpl2015
HTTP Debugging
#droidconpl2015
HTTP Debugging• mitmproxy
• Fiddler
• Charles proxy
#droidconpl2015
Charles Proxy
• Simulate a laggy/unstable connec3on
• Repeat queries
• Check the responses
• Add some breakpoints to
• Cancel an HTTP(s) call
• Edit a request
• Edit a response
#droidconpl2015
Cancel a request
#droidconpl2015
Edit a response + Simulate slow connec4on
#droidconpl2015
MeasuringTes$ng
Analyzing#droidconpl2015
Developer Op*ons
#droidconpl2015
#droidconpl2015
#droidconpl2015
#droidconpl2015
hierarchyviewer 2
$ export ANDROID_HVPROTO=ddm$ exec ${ANDROID_HOME}/tools/monitor
2 Documenta,on: h/ps://developer.android.com/tools/performance/hierarchy-viewer/setup.html#hvproto-variableh/p://developer.android.com/tools/debugging/debugging-ui.html
#droidconpl2015
#droidconpl2015
Hierarchy viewer
Pro$p from +EvelioTarazonaCáceres
@ViewDebug.ExportedProperty(category="avatar")private String mLastUrl;
#droidconpl2015
uiautomatorviewer
$ exec ${ANDROID_HOME}/tools/uiautomatorviewer
#droidconpl2015
Anima&ons
Developer op)ons -> Anima)on scale
#droidconpl2015
Anima&ons
Make a screencast:
$ adb shell screenrecord /sdcard/demo.mp4$ adb pull /sdcard/demo.mp4
VLC :
Press the keyboard E key to see frames one by one
#droidconpl2015
apktool + dex2jar + JD-GUIh"p://ibotpeaches.github.io/Apktool
h"ps://github.com/pxb1988/dex2jar
h"p://jd.benow.ca
#droidconpl2015
Stetho
#droidconpl2015
Stetho - UI
#droidconpl2015
Stetho - Network
#droidconpl2015
Stetho - Resources
#droidconpl2015
Stetho - Dumpapp
#droidconpl2015
Stetho - Dumpapp
#droidconpl2015
Stetho - Custom pluginh"p://code.tutsplus.com/tutorials/debugging-android-apps-with-facebooks-stetho--cms-24205
class AppDumperPlugin implements DumperPlugin { @Override public String getName() { return "my_plugin"; }
@Override public void dump(DumperContext dumpContext) throws DumpException { PrintStream writer = dumperContext.getStdout(); String commandName = (args.isEmpty()) ? "" : args.remove(0);
if ("test".equals(commandName)) { out.println("Hello, World!"); } }}
#droidconpl2015
Stetho - Custom plugin
#droidconpl2015
Stetho - Dumpapp (example)(ActivityProvider in a dependency graph in debug)
@Singletonpublic class ActivityProvider implements Application.ActivityLifecycleCallbacks {
private Activity mCurrentActivity;
@Inject public ActivityProvider(Application app) { app.registerActivityLifecycleCallbacks(this); }
public Activity getCurrentActivity() { return mCurrentActivity; }
@Override public void onActivityResumed(Activity activity) { mCurrentActivity = activity; }
@Override public void onActivityPaused(Activity activity) { mCurrentActivity = null; }}
#droidconpl2015
Stetho - Dumpapp (example)
AppDumperPlugin.java
private void doProfileData(PrintStream writer) { Activity activity = mActivityProvider.getCurrentActivity(); if (activity instanceof ProfileActivity) { try { // Use reflection to access private "mUser" field Field field = ProfileActivity.class.getDeclaredField("mUser"); field.setAccessible(true); UserModel user = (UserModel) field.get(activity); writer.println(new GsonBuilder().setPrettyPrinting().create().toJson(user)); } catch (Exception e) { writer.println(e.getMessage()); } }}
#droidconpl2015
Sample appCheckout the commit history for an implementa4on of all those tools
(Takt, Hugo, SonarQube, Mock Server, Stetho /w realm/dumpapp)in the droidcon PL app:
hFps://github.com/Nilhcem/droidcon-2015-mobile-app/tree/toolbox
#droidconpl2015
Measuring
Tes$ng
Analyzing
#droidconpl2015
Measuring
Tes$ng
Analysing
Also...
#droidconpl2015
DevDrawerh"ps://play.google.com/store/
apps/details?id=com.owentech.DevDrawer
#droidconpl2015
Lockito
#droidconpl2015
ViewInspectorh"ps://github.com/xfumihiro/ViewInspector
#droidconpl2015
Methodscount
h"p://www.methodscount.com/h"ps://twi"er.com/dmarcato/status/672487137204297728/photo/1
#droidconpl2015
As a conclusion...
#droidconpl2015
Choose according to your needs and tastes
#droidconpl2015
The 2015 Android Developer Toolbox
#droidconpl2015
(Example of an)Android Developer Toolbox
#droidconpl2015
Master your tools
to build be*er apps
❤
h"ps://twi"er.com/Nilhcem
h"ps://plus.google.com/+Gau2erMechling
h"ps://www.happn.com#droidconpl2015