Date post: | 11-Jan-2017 |
Category: |
Technology |
Upload: | nilhcem |
View: | 468 times |
Download: | 0 times |
The 2016 Android Developer Toolbox
#droidconIT
@Nilhcem
Gau$er Mechling
Aspiring So+ware Cra+sman
#droidconIT
happn"Ritrova le persone che incroci"
#droidconIT
"So you're telling me
we need a toolbox?"
#droidconIT
#droidconIT
"Use the right tools for the right job"
#droidconIT
#droidconIT
#droidconIT
Gradle(with the Android Plugin for Gradle)
#droidconIT
Build Variants
#droidconIT
Debug screenExample from Google iosched
#droidconIT
Internal se*ngs app
Similar to u2020 Sample app
• Display build / device informa6on
• Change endpoint (restart process with JakeWharton/ProcessPhoenix)
• Show logs (pedrovgs/Lynx)
• Allow easy bug report capturing (maFprecious/telescope)
• Enable/Disable Takt / Stetho /
#droidconIT
Droidcon Turin applica.on for
hipster developersh"ps://github.com/
Nilhcem/droidconit-2016
#droidconIT
Measuring
Tes$ng
Analyzing
#droidconIT
MeasuringTes$ng
Analyzing
#droidconIT
Android Studio(Android Monitor tab)
#droidconIT
#droidconIT
Detect Memory Leaks
#droidconIT
#droidconIT
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(); }}
#droidconIT
Hugoh"ps://github.com/JakeWharton/hugo
Prefix classes/methods with:
@DebugLog
Result:
DroidconApp V ⇢ onCreate()
V ⇢ initGraph()
V ⇠ initGraph [13ms]
V ⇢ initLogger()
V ⇠ initLogger [1ms]
V ⇠ onCreate [73ms]
#droidconIT
Pidcath"ps://github.com/JakeWharton/pidcat
$ pidcat com.nilhcem.droidconit
#droidconIT
AndroidDevMetricsh"ps://github.com/frogermcs/
AndroidDevMetrics
apply plugin: 'com.frogermcs.androiddevmetrics'
public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); AndroidDevMetrics.initWith(this); }}
#droidconIT
#PerfMa(ers
#droidconIT
#QualityFirst
#droidconIT
Code sta)c analysis tools
#droidconIT
Code sta)c analysis tools• Lint
• PMD
• Checkstyle
• Findbugs
• Facebook's infer
#droidconIT
SonarQube
#droidconIT
SonarQube 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.4.zipRUN unzip -qq sonarqube-5.4.zip -d /opt/RUN rm sonarqube-5.4.zip
EXPOSE 9000
CMD ["/opt/sonarqube-5.4/bin/linux-x86-64/sonar.sh", "console"]
Then launch:
docker build -t nilhcem/sonarqube .docker run -p 9000:9000 -d nilhcem/sonarqube
#droidconIT
SonarQube Gradle Configura1on
apply plugin: 'org.sonarqube'
sonarqube { properties { def appProject = project(':app') def appProjectBuildDir = appProject.buildDir
property 'sonar.projectKey', 'droidconit' property 'sonar.projectName', 'DroidconIT 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
#droidconIT
#droidconIT
#droidconIT
Measuring
Tes$ngAnalyzing
#droidconIT
Mock Server
#droidconIT
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');
/* Speakers list */app.get('/speakers', function(req, res) { res.type('application/json; charset=utf8'); res.status(200).send(fs.readFileSync('data/speakers.json', 'utf8'));});
/* Other web services */// ...
/* Starting the server */app.listen(port, function () { console.log('Express server listening on port ' + port);});
#droidconIT
NodeJS + Express: Slow servicesleep(2000);
// Ugly, but does the job :)function sleep(durationMillis) { var now = new Date().getTime(); while(new Date().getTime() < now + durationMillis) { // do nothing }}
#droidconIT
Example
h"ps://github.com/Nilhcem/droidconit-2016/tree/master/mockserver
$ npm install$ node server.js
Then, go tohttp://localhost:8990/
#droidconIT
Hosts Editor
h"ps://play.google.com/store/apps/details?id=com.nilhcem.hostseditor
#droidconIT
HTTP Debugging
#droidconIT
HTTP Debugging• mitmproxy
• Fiddler
• Charles proxy
#droidconIT
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
#droidconIT
Cancel a request
#droidconIT
Edit a response
#droidconIT
MeasuringTes$ng
Analyzing#droidconIT
Developer Op*ons
#droidconIT
#droidconIT
#droidconIT
hierarchyviewerh"ps://developer.android.com/tools/performance/hierarchy-viewer/
setup.html#hvproto-variableh"p://developer.android.com/tools/debugging/debugging-ui.html
$ export ANDROID_HVPROTO=ddm$ exec ${ANDROID_HOME}/tools/monitor
#droidconIT
uiautomatorviewer
#droidconIT
Anima&ons
Developer op)ons -> Anima)on scale
#droidconIT
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
#droidconIT
apktool + dex2jar + JD-GUIh"p://ibotpeaches.github.io/Apktoolh"ps://github.com/pxb1988/dex2jar
h"p://jd.benow.ca
#droidconIT
Stetho
#droidconIT
Stetho - UI
#droidconIT
Stetho - Network
#droidconIT
Stetho - Resources
#droidconIT
Stetho - Dumpapp
#droidconIT
Stetho - Dumpapp
#droidconIT
Stetho - Dumpapp
#droidconIT
Some more dumpapp examples
#droidconIT
$ dumpapp accessToken invalidate
$ dumpapp accessToken showfce1235425dcdeadbeef8cafebabe42
$ dumpapp clipboard getHello
$ dumpapp clipboard set "Text to copy"$ dumpapp onTrimMemory$ dumpapp openIntent scheme://open/speaker/3
$ dumpapp gcmTokenuHyMKnEQ:APA91bEHZ6afFLQQMzKgSDjp5y_0397usitPqj_Bp02
$ dumpapp geolocDataLocation[fused 22.5430883,114.1043205 acc=21 et=+21m5s492ms]
$ dumpapp runningServicescom.example.LocationService
#droidconIT
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_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!"); } }}
#droidconIT
Stetho - Custom plugin
#droidconIT
Stetho - Dumpapp (example)(ActivityProvider in a dependency graph in debug)
@Singletonpublic 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; }}
#droidconIT
Stetho - Dumpapp (example)
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()); } }}
#droidconIT
Stetho console + Rhino
#droidconIT
Measuring
Tes$ng
Analyzing
#droidconIT
Measuring
Tes$ng
Analysing
Lastly
#droidconIT
ADB + Shell# Open a deep linking intentadb shell am start -a android.intent.action.VIEW -d "scheme://app/deep/linking"
# List running servicesadb shell dumpsys activity services
# Get the path of an install applicationadb shell pm path app.package.name
# Clear app dataadb shell pm clean app.package.name
# Take a screenshotadb shell screencap -p | perl -pe '\''s/\x0D\x0A/\x0A/g'\'' > screen.png
# Paste text from your computer clipboard to your android devicepbpaste | sed "s/%/%%/g" | sed "s/ /\%\s/g" | xargs adb shell input text
#droidconIT
Lockito
#droidconIT
Fill RAMOn-device low-memory tes2ng for Android
h"ps://play.google.com/store/apps/details?id=com.tspoon.androidtoolbelt
#droidconIT
ViewInspectorh"ps://github.com/xfumihiro/ViewInspector
#droidconIT
Methodscounth"p://www.methodscount.com/
h"ps://github.com/mihaip/dex-method-counts
#droidconIT
As a conclusion...
#droidconIT
Choose according to your needs and tastes
#droidconIT
The 2016 Android Developer Toolbox
#droidconIT
(Example of an)Android Developer Toolbox
#droidconIT
❤ Master your toolsto build be*er apps ❤
h"ps://twi"er.com/Nilhcem
h"ps://github.com/Nilhcem/droidconit-2016
h"p://www.slideshare.net/Nilhcem/the-2016-android-developer-toolbox-italy
#droidconIT