Upgrade to Pro — share decks privately, control downloads, hide ads and more …

THE 2016 ANDROID DEVELOPER TOOLBOX - GAUTIER MECHLING

1fa9cb8c7997c8c4d3d251fb5e41f749?s=47 Realm
October 22, 2016

THE 2016 ANDROID DEVELOPER TOOLBOX - GAUTIER MECHLING

Whether your native Android app is a pet project or has millions of users, you probably need the right tools, during the development, to help you modify persisted data in real time, simulate an slow/unstable HTTP(s) connection, detect bugs as fast as possible, or create mock servers to anticipate the development of a feature. We'll make a demonstration of all the tools we use, in 2016, to write maintainable code and improve our productivity.

1fa9cb8c7997c8c4d3d251fb5e41f749?s=128

Realm

October 22, 2016
Tweet

Transcript

  1. #mobilization2016 THE 2016 ANDROID DEVELOPER TOOLBOX

  2. @Nilhcem

  3. #mobilization2016

  4. THE 2016 ANDROID DEVELOPER TOOLBOX

  5. None
  6. "Use the right tools for the right job"

  7. None
  8. None
  9. (with the Android Plugin for Gradle)

  10. BUILD VARIANTS

  11. U+2020 https://github.com/JakeWharton/u2020

  12. DEBUG SCREEN Example from Google iosched

  13. INTERNAL SETTINGS APP Similar to U+2020 Sample app Display build

    / device information Change endpoint (restart process with ) Show logs ( ) Allow easy bug report capturing ( ) Enable/Disable Takt / Stetho / Scalpel / Madge... JakeWharton/ProcessPhoenix pedrovgs/Lynx mattprecious/telescope
  14. MOBILIZATION 2016 APPLICATION https://github.com/Nilhcem/mobilization-2016

  15. MEASURING TOOLS

  16. ANDROID STUDIO (Android Monitor tab)

  17. None
  18. DETECT MEMORY LEAKS

  19. None
  20. LEAK CANARY https://github.com/square/leakcanary

  21. FRAME RATE build.gradle: MyApplication.java: https://github.com/wasabeef/Takt compile 'jp.wasabeef:takt:1.0.3' public class MyApplication

    extends Application { @Override public void onCreate() { super.onCreate(); Takt.stock(this).play(); } }
  22. HUGO https://github.com/JakeWharton/hugo Prefix classes/methods with: @DebugLog Result: MobilizationApp V ⇢

    onCreate() V ⇢ initGraph() V ⇠ initGraph [13ms] V ⇢ initLogger() V ⇠ initLogger [1ms] V ⇠ onCreate [73ms]
  23. PIDCAT https://github.com/JakeWharton/pidcat $ pidcat com.nilhcem.mobilization

  24. ANDROIDDEVMETRICS build.gradle: MyApplication.java: https://github.com/frogermcs/AndroidDevMetrics apply plugin: 'com.frogermcs.androiddevmetrics' public class MyApplication

    extends Application { @Override public void onCreate() { super.onCreate(); AndroidDevMetrics.initWith(this); } }
  25. CODE STATIC ANALYSIS TOOLS Lint Error Prone (Google) Infer (Facebook)

  26. None
  27. None
  28. None
  29. SONARQUBE Dockerfile: FROM java:8 MAINTAINER Nilhcem RUN DEBIAN_FRONTEND=noninteractive apt update

    RUN DEBIAN_FRONTEND=noninteractive apt install -y wget unzip RUN wget -q https://sonarsource.bintray.com/Distribution/sonarqube/sonarqube-6.1.zip RUN unzip -qq sonarqube-6.1.zip -d /opt/ RUN rm sonarqube-6.1.zip EXPOSE 9000 CMD ["/opt/sonarqube-6.1/bin/linux-x86-64/sonar.sh", "console"] Then launch: $ docker build -t nilhcem/sonarqube . $ docker run -p 9000:9000 -d nilhcem/sonarqube
  30. SONARQUBE GRADLE CONFIGURATION build.gradle: apply plugin: 'org.sonarqube' sonarqube { properties

    { def appProject = project(':app') def appProjectBuildDir = appProject.buildDir property 'sonar.projectKey', 'mobilization' property 'sonar.projectName', 'Mobilization 2016' property 'sonar.projectVersion', appProject.android.defaultConfig.versionName property 'sonar.host.url', 'http://localhost:9000' property 'sonar.sources', 'src' property 'sonar.sourceEncoding', 'UTF-8' property 'sonar.java.binaries', 'build/intermediates/classes/production/debug' property 'sonar.java.test.binaries', 'build/intermediates/classes/test/production/debug' property 'sonar.exclusions', 'src/test/java/**' property 'sonar.core.codeCoveragePlugin', 'jacoco' property 'sonar.jacoco.reportPath', "$appProjectBuildDir/jacoco/testProductionDebugUnitTest.exec" property 'sonar.junit.reportsPath', "$appProjectBuildDir/test-results/testProductionDebugUnitTest/productionDebug" } } Then launch: ./gradlew :app:assembleProductionDebug :app:testProductionDebugUnitTest :app:sonarqube
  31. None
  32. None
  33. TESTING TOOLS

  34. MOCK SERVER

  35. 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); });
  36. NODEJS + EXPRESS Slow service sleep(2000); function sleep(durationMillis) { var

    now = new Date().getTime(); while (new Date().getTime() < now + durationMillis) { // do nothing } } // Please do not take pictures of this slide, // This is not something I am proud of
  37. EXAMPLE Then, go to: https://github.com/Nilhcem/mobilization-2016 /tree/master/mockserver $ npm install $

    npm start http://localhost:8990/
  38. HOSTS EDITOR https://play.google.com/store/apps/details?id=com.nilhcem.hostseditor

  39. HTTP DEBUGGING

  40. HTTP DEBUGGING mitmproxy Fiddler Charles proxy

  41. CHARLES PROXY Simulate a slow connection Repeat queries Check the

    responses Add some breakpoints to: Cancel an HTTP(s) call Edit a request Edit a response
  42. ANDROID STATE RESTORING

  43. DON'T KEEP ACTIVITIES

  44. FILL RAM https://play.google.com/store/apps/details?id=com.tspoon.androidtoolbelt

  45. ANDROID DEVICE MONITOR - STOP PROCESS

  46. ANALYZING TOOLS

  47. DEVELOPER OPTIONS

  48. None
  49. None
  50. UIAUTOMATORVIEWER

  51. ANIMATIONS Developer options -> Animation scale

  52. ANIMATIONS Make a screencast (API 19+): VLC : $ adb

    shell screenrecord /sdcard/demo.mp4 $ adb pull /sdcard/demo.mp4 Press the keyboard 'E' key to see frames one by one
  53. APKTOOL + DEX2JAR + JD-GUI http://ibotpeaches.github.io/Apktool https://github.com/pxb1988/dex2jar http://jd.benow.ca

  54. JADX https://github.com/skylot/jadx

  55. ANDROID STUDIO (Build > Analyze APK)

  56. STETHO

  57. STETHO - UI

  58. STETHO - NETWORK

  59. STETHO DUMPAPP

  60. STETHO - DUMPAPP

  61. SOME MORE DUMPAPP EXAMPLES $ 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
  62. STETHO - CUSTOM PLUGIN 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!"); } } }
  63. STETHO - CUSTOM PLUGIN

  64. STETHO - DUMPAPP (EXAMPLE) (ActivityProvider in a dependency graph in

    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; } }
  65. 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()); } } }
  66. $#*!, I FORGOT THESE TOOLS!

  67. ADB + SHELL # Open a deep linking intent adb

    shell am start -a android.intent.action.VIEW -d "scheme://app/deep/linking" # List running services adb shell dumpsys activity services # Get the path of an install application adb shell pm path app.package.name # Clear app data adb shell pm clean app.package.name # Take a screenshot adb shell screencap -p | perl -pe '\''s/\x0D\x0A/\x0A/g'\'' > screen.png # Paste text from your computer clipboard to your android device pbpaste | sed "s/%/%%/g" | sed "s/ /\%\s/g" | xargs adb shell input text
  68. POSTMAN https://www.getpostman.com/

  69. LOCKITO https://play.google.com/store/apps/details?id=fr.dvilleneuve.lockito

  70. ACCESSIBILITY SCANNER https://play.google.com/store/apps/details?id=com.google.android.apps.accessibility.auditor

  71. VYSOR http://www.vysor.io

  72. AS A CONCLUSION...

  73. CHOOSE ACCORDING TO YOUR NEEDS AND TASTES

  74. THE 2016 ANDROID DEVELOPER TOOLBOX

  75. (EXAMPLE OF AN) ANDROID DEVELOPER TOOLBOX

  76. https://twitter.com/Nilhcem https://github.com/Nilhcem/mobilization-2016 http://www.slideshare.net/Nilhcem/the-2016-android-developer-toolbox-mobilization MASTER YOUR TOOLS TO BUILD BETTER APPS