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

THE 2016 ANDROID DEVELOPER TOOLBOX - GAUTIER MECHLING

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.

Realm

October 22, 2016
Tweet

More Decks by Realm

Other Decks in Technology

Transcript

  1. 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
  2. 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(); } }
  3. 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]
  4. 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
  5. 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
  6. 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); });
  7. 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
  8. 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
  9. 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
  10. 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
  11. 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!"); } } }
  12. 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; } }
  13. 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()); } } }
  14. 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