[Droidcon Greece '19] My love-hate relationship with Android Studio

[Droidcon Greece '19] My love-hate relationship with Android Studio

Android Studio is the tool of the trade hands down. When it comes to Android (app/library/IoT) development, the first thing that comes to mind is to install Android Studio and get going from there. However, it has not been a smooth road as expected for me. In my own experience, I talk about my love-hate relationship with Android Studio. I try to cover what Android Studio gets right and what it doesn't. The talk focuses on how to be embrace performance when Android Studio is the bottleneck in the workflow (slow build times and reduced productivity), how switching to a terminal and various tools that exist in the ecosystem can give Android developers the much-needed speed boost and in-depth view in their development workflow. By the end of this talk, you would have embraces a workflow that allows for increased productivity and faster development.

Google Slides: https://docs.google.com/presentation/d/1sO_F9sGIEuaxtmRkVRuZZmM2YhmZK7BVmHjzIhOvcmE/edit?usp=sharing

Event: https://web.archive.org/web/20190921200216/https://droidcon.gr/agenda/

Ab4fa54bccd8073d0c0b4d4a2dd4193f?s=128

Nishant Srivastava

September 25, 2019
Tweet

Transcript

  1. 2

  2. The disclaimer @nisrulz 3

  3. Where it started @nisrulz 4

  4. What happened • Trying to build an Android Project ◦

    Typical project ◦ Multi module 5 @nisrulz
  5. What happened • Trying to build an Android Project ◦

    Native code (NDK) ◦ Common dependencies: Retrofit, Dagger, Rx, Support Libraries, etc 6 @nisrulz
  6. What happened • Laptop: Macbook Air (early 2014) ◦ Core

    i5(1.4 Ghz) ◦ 4GB DDR3 RAM ◦ 128GB SSD ◦ Intel HD Graphics (1.5GB) 7 @nisrulz
  7. What happened My build times: ~37 min 8 @nisrulz

  8. What happened My build times: ~37 min Not just the

    first time, but every other build after that too 9 @nisrulz
  9. What happened My build times: ~37 min …and not only

    that 10 @nisrulz
  10. What happened ...but also 11 @nisrulz

  11. What happened With a few gradle tweaks in the project.

    12 @nisrulz https://guides.gradle.org/performance/
  12. What happened Build times down to ~28 min With a

    few gradle tweaks in the project. 13 @nisrulz https://guides.gradle.org/performance/
  13. What happened 14 @nisrulz After exhausting all possibilities.

  14. What happened Switched to Terminal builds and VS Code Editor.

    15 @nisrulz + After exhausting all possibilities.
  15. What happened 16 @nisrulz +

  16. What happened 17 @nisrulz + Final result.

  17. What happened 18 @nisrulz + Build times down to ~3

    minutes( 89% reduction) Final result.
  18. 19 @nisrulz How I reduced my Android build times by

    89%
  19. 20 @nisrulz I was just happy that I was not

    in a spot like this guy
  20. The experience. @nisrulz 21

  21. The experience State of speed: Slow 22 @nisrulz

  22. The experience Basically this... State of speed: Slow 23 @nisrulz

  23. The experience State of speed: Slow 24 @nisrulz

  24. The experience State of reliability: Critical issues 25 @nisrulz

  25. The experience State of reliability: Critical issues 26 @nisrulz https://issuetracker.google.com/issues/133864394

  26. The experience State of reliability: Critical issues 27 @nisrulz https://issuetracker.google.com/issues/133864394

  27. The experience State of reliability: Critical issues 28 @nisrulz ~3

    months https://issuetracker.google.com/issues/133864394
  28. The experience State of reliability: Finicky 29 @nisrulz

  29. The experience State of reliability: Finicky 30 @nisrulz

  30. The experience To a point where someone had to build

    this: A nuke script! https://github.com/rock3r/deep-clean 31 @nisrulz
  31. The experience - Tweet dated: 26 July 2019 - Android

    Studio 3.5 Stable (released): 20 August 2019 > Was already on bleeding edge 32 @nisrulz https://twitter.com/nisrulz/status/1154760 114026532864
  32. The experience 33 @nisrulz https://twitter.com/nisrulz/status/1154758411684392961

  33. The experience State of polish: 34 @nisrulz https://www.reddit.com/r/androiddev/c omments/d271hc/wildly_infuriating/

  34. The experience State of choice: Forced, deviates from base 35

    @nisrulz
  35. The experience State of memory consumption: Not suitable 36 @nisrulz

  36. The experience State of memory consumption: Not suitable 37 @nisrulz

  37. The experience State of memory consumption: Not suitable 38 @nisrulz

  38. The experience State of CPU consumption: Unacceptable 39 @nisrulz

  39. The experience State of CPU consumption: Unacceptable 40 @nisrulz

  40. The experience State of updates: Unreliable 41 @nisrulz

  41. The experience State of result: false-positives 42 @nisrulz

  42. The experience State of result: false-positives 43 @nisrulz

  43. The experience State of tools: Limited 44 @nisrulz Energy Profiler

  44. The experience State of tools: Limited 45 @nisrulz Constraint Layout

    Editor
  45. The experience State of tools: Limited 46 @nisrulz Resource Manager

  46. The experience State of tools: Limited 47 @nisrulz Apply Changes

  47. The experience State of tools: Limited 48 @nisrulz Apply Changes

    https://medium.com/androiddevelopers/android-studio-pro ject-marble-apply-changes-e3048662e8cd
  48. The experience State of tools: Limited 49 @nisrulz Apply Changes

    https://developer.android.com/studio/known-issues#appl y-changes-ki-verification-errors
  49. The experience State of tools: Limited 50 @nisrulz Deployments

  50. The experience To summarize, Android Studio is • Slow •

    Finicky • Forces its defaults and deviates from its base 51 @nisrulz
  51. The experience To summarize, Android Studio is • New tools

    are limiting ◦ Energy Profiler ◦ Constraint Layout Editor ◦ Resource Manager ◦ Apply Changes ◦ Deployments options 52 @nisrulz
  52. The experience To summarize, Android Studio is • Uses a

    lot of Memory and CPU • Has versioning quality problem (Stable, Beta, Alpha) 53 @nisrulz
  53. and Workarounds. @nisrulz 54

  54. Slow, but why? • Gradle Configuration • Indexing changes in

    code • Plugins • Code Insight: Inplace analysis/inspections 55 @nisrulz
  55. Configuring Gradle for speed Use the latest Gradle release. 56

    @nisrulz Incremental compile 1000-module Java project https://gradle.org/whats-new/gradle-5/
  56. Configuring Gradle for speed Use the latest Gradle release. Caveat:

    Update to latest Canary release of Android Studio, since the support for latest Gradle is tied to Android Studio release. 57 @nisrulz
  57. Configuring Gradle for speed Build Cache: Reuse outputs from any

    previous invocation of Gradle // Add this in your global gradle.properties file // at ~/.gradle/gradle.properties // Enable Build Cache android.enableBuildCache=true 58 @nisrulz
  58. Configuring Gradle for speed Daemon: Dedicated background process to improve

    performance of Gradle // Add this in your global gradle.properties file // at ~/.gradle/gradle.properties // Enable Gradle Daemon org.gradle.daemon=true 59 @nisrulz
  59. Configuring Gradle for speed Allocate memory: Increase the memory provided

    to JVM // Add this in your global gradle.properties file // at ~/.gradle/gradle.properties // Configure allocated memory org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m 60 @nisrulz
  60. Configuring Gradle for speed Parallel builds: Force Gradle to execute

    tasks in parallel as long as those tasks are in different projects. // Add this in your global gradle.properties file // at ~/.gradle/gradle.properties // Enable Parallel builds org.gradle.parallel=true 61 @nisrulz
  61. Configuring Gradle for speed Execution: Prefer running specific task over

    general ones // Creates AAR for every module and all variants! ./gradlew assemble // Creates AAR for every module’s debug variant ./gradlew assembleDebug // Creates AAR for only `mymodule` in debug variant! ./gradlew :mymodule:assembleDebug 62 @nisrulz
  62. Reducing Indexing If your codebase has files changing on each

    build, it will trigger indexing. 63 @nisrulz
  63. Reducing Indexing Suggestions: • Avoid using annotation processors Or use

    incremental annotation processors • Using implementation as much as possible, instead of api. • Use static build config values i.e version code, version name, resources 64 @nisrulz
  64. Plugins: Inspect what you use Android Studio comes with a

    lot of Plugins enabled, which contribute to its sluggishness. 65 @nisrulz
  65. Plugins: Inspect what you use Solution: Check and disable what

    you don’t need. 66 @nisrulz
  66. Code Insight Although required, it does make Android Studio slow.

    Solution: Enable Power Save Mode 67 @nisrulz
  67. Terminal to the rescue. @nisrulz 68

  68. ADB: Android Debug Bridge • Command Line tool • Shipped

    with Android SDK • Allows interacting with debuggable Android devices • Client-Server program • Available as: adb <param> 69 @nisrulz
  69. ADB: Android Debug Bridge • Install App ◦ adb install

    path_to_apk • Uninstall App ◦ adb uninstall com.package.name 70 @nisrulz
  70. ADB: Android Debug Bridge • Copy a file from System

    to Android device ◦ adb push path_to_file /path_to_dir_on_device • Copy a file from Android device to System ◦ adb pull /path_to_dir_on_device/file.png ~/path_on_system/ 71 @nisrulz
  71. Other tools via ADB shell • Activity Manager: am •

    Emulator: emulator • Package Manager: pm • Device Policy Manager: dpm • Logcat: logcat • Dumpsys: dumpsys ...and many more. 72 @nisrulz
  72. Gradle Android projects use Gradle as the build system. Each

    Android project has a gradle wrapper, which is a proxy to local Gradle binary. Android Studio invokes Gradle to execute tasks 73 @nisrulz
  73. Gradle The same can be done via terminal: ./gradlew assembleDebug

    > is equivalent to Make in Android studio 74 @nisrulz
  74. Lint This is part of the gradle tasks, which checks

    the code for structural inconsistencies, thus allowing to write more maintainable code. // Execute lint in project ./gradlew lint > Similar to executing via Android Studio 75 @nisrulz
  75. Lint 76 @nisrulz

  76. Detekt https://github.com/arturbosch/detekt • Static code analyzer for Kotlin language. •

    Helps to detect code smell in kotlin codebase 77 @nisrulz
  77. Detekt https://github.com/arturbosch/detekt • Highly configurable • Enables complexity analysis of

    the code • Also has a gradle plugin to setup in the project 78 @nisrulz
  78. Detekt https://github.com/arturbosch/detekt // Execute at the root of the project

    java -jar /path_to/detekt-cli.jar --debug 79 @nisrulz
  79. Detekt // Execute at the root of the project java

    -jar /path_to/detekt-cli.jar --debug // Output Complexity Report: - 686 lines of code (loc) - 563 source lines of code (sloc) - 425 logical lines of code (lloc) - 32 comment lines of code (cloc) ... - 218 code smells per 1000 lloc Project Statistics: - number of properties: 73 - number of functions: 22 - number of classes: 5 - number of packages: 3 - number of kt files: 5 80 @nisrulz
  80. Classyshark https://github.com/google/andr oid-classyshark Tool for decompiling and analyzing internals of

    an APK such as dex Count. Works with .apk, .jar, .aar, .class, .dex or .so files. 81 @nisrulz
  81. Classyshark https://github.com/google/andr oid-classyshark Execute: java -jar ClassyShark.jar 82 @nisrulz

  82. Classyshark 83 @nisrulz

  83. Classyshark 84 @nisrulz

  84. AVD Manager • Command line tool to create and manage

    Android Virtual Devices (AVD) • Located in android_sdk/tools/bin/ 85 @nisrulz
  85. AVD Manager // List all avd avdmanager list // Create

    a new avd avdmanager create avd -n myavd -k "system-images;android-29;google_apis;x86" // Remove avd avdmanager delete avd -n myavd 86 @nisrulz
  86. Scrcpy https://github.com/Genymobile/scrcpy Command-line tool for mirroring and controlling your device.

    // Start mirroring the device scrcpy //Record while mirroring scrcpy --record file.mp4 87 @nisrulz
  87. Scrcpy https://github.com/Genymobile/scrcpy Command-line tool for mirroring and controlling your device.

    // Show touches scrcpy --show-touches // Switch off screen scrcpy --turn-screen-off 88 @nisrulz
  88. SDK Manager • Command line tool to manage Android SDK

    • Used to view, install, remove packages in Android SDK • Located in android_sdk/tools/bin/ 89 @nisrulz
  89. SDK Manager // List all available packages sdkmanager --list //

    Install packages sdkmanager packages // Remove packages sdkmanager --uninstall packages // Update all packages sdkmanager --update 90 @nisrulz
  90. Battery Historian https://github.com/google/battery-historian • Python based tool • Used to

    inspect battery related information and events, while the device was not plugged in 91 @nisrulz
  91. Battery Historian https://github.com/google/battery-historian • For Android device running Android 5.0

    Lollipop (API level 21) and later. • Useful since the new Energy Profilers are Android Studio only. 92 @nisrulz
  92. Battery Historian 93 @nisrulz

  93. Battery Historian 94 @nisrulz

  94. IntelliJ Idea • Android Studio is based on IntelliJ Idea

    ◦ IntelliJ Idea can be used for Android Development • Faster for development 95 @nisrulz
  95. IntelliJ Idea • Consumes less memory/CPU than Android Studio •

    Full plugin support • More frequent updates 96 @nisrulz
  96. IntelliJ Idea • Doesn’t have the Android Studio specific tools

    ◦ Constraint Layout Editor ◦ Profilers ◦ Resource Manager ◦ Apply Changes 97 @nisrulz
  97. Mainframer • Build your project remotely on a better hardware

    • Uses rsync to sync changes over ssh and then builds the project, syncs the apk back. https://github.com/buildfoundation/mainframer 98 @nisrulz
  98. Automation • Alias creation enables executing complex tool configuration as

    a simple command. Example: // Create alias to push release apk to Downloads folder in Device alias pushReleaseToDevice="adb push ./apk-release.apk /sdcard/Downloads" // Execute pushReleaseToDevice ↵ 99 @nisrulz
  99. Automation • Command line tools enable ability to include in

    scripts. Using alias simplify the process. # Install APK to device # Use: apkinstall app-debug.apk alias apkinstall="adb devices | tail -n +2 | cut -sf 1 | xargs -I X adb -s X install -r $1" 100 @nisrulz
  100. Automation • Command line tools enable ability to include in

    scripts. Using alias simplify the process. # As an alternative to apkinstall, you can also do just ./gradlew installDebug # # Alias for building and installing the apk to connected device # Run at the root of your project # Usage: buildAndInstallApk alias buildAndInstallApk='./gradlew assembleDebug && apkinstall ./app/build/outputs/apk/debug/app-debug.apk' 101 @nisrulz
  101. Automation • Command line tools enable ability to include in

    scripts. Using alias simplify the process. # Launch your debug apk on your connected device # Execute at the root of your android project # Usage: launchDebugApk function launchDebugApk(){ local APP_PACKAGE_NAME=$(getPackageName ./app/build/outputs/apk/debug/app-debug.apk) adb shell monkey -p $APP_PACKAGE_NAME 1 1>/dev/null 2>&1; } 102 @nisrulz
  102. Automation • Command line tools enable ability to include in

    scripts. Using alias simplify the process. # ------------- Single command to build+install+launch apk------------# # Execute at the root of your android project # Use as: buildInstallLaunchDebugApk alias buildInstallLaunchDebugApk="buildAndInstallApk && launchDebugApk" 103 @nisrulz
  103. Automation • Command line tools enable ability to include in

    scripts. Using alias simplify the process. # Take screenshot alias screenshot="adb exec-out screencap -p > screen-$(nowdate).png" # Remove app alias rmapp="adb devices | tail -n +2 | cut -sf 1 | xargs -I X adb -s X uninstall $1" # Clear data for app alias clearapp="adb devices | tail -n +2 | cut -sf 1 | xargs -I X adb -s X shell pm clear $1" More automation aliases: https://gist.github.com/nisrulz/b0e79f2b3e27f99ca8b5dba9db6281ec 104 @nisrulz
  104. Automation++ • adbe : ADB Enhanced - Script to execute

    adb commands on all connected devices. # Usage # Run any command you would run with adb for all the connected devices # ./adbe <command> is the equivalent of ./adb -s <serial number> <command> # # Examples # ./adbe version ./adbe install demo_app.apk 105 @nisrulz https://github.com/nisrulz/terminal-utils/blob/master/android/adbe.sh
  105. Automation++ • adbe : ADB Enhanced // Script body adb

    devices | while read line do if [ ! "$line" = "" ] && [ `echo $line | awk '{print $2}'` = "device" ] then device=`echo $line | awk '{print $1}'` echo "$device $@ ..." adb -s $device $@ fi done 106 @nisrulz
  106. Automation • Use gradle plugin to setup all the automation

    commands Novoda’s Gradle Android command plugin creates handy gradle tasks in the project itself. https://github.com/novoda/gradle-android-command-plugin 107 @nisrulz
  107. Automation • Use gradle plugin to setup all the automation

    commands Some commands available: • installDevice<Variant> - installs the app on a specific device. • uninstallDevice<Variant> - uninstalls the app from a specific device. • run<Variant> - installs and launches the app on a specific device. and many more. Execute: ./gradlew installDeviceDebug 108 @nisrulz
  108. The experience. @nisrulz 109

  109. The experience • Project Marble Project Marble is a multi-release

    and focused effort on making fundamental features of the IDE rock-solid and polished. 110 @nisrulz
  110. The experience • Project Marble Already made improvements under: 1.

    UX and performance in Layout Editor 2. Instant Run has been replaced by Apply Changes 3. Emulator performance, Snapshots 4. Lint performance 111 @nisrulz
  111. The experience • Project Marble Issues: https://developer.android.com/studio/known-issues 112 @nisrulz

  112. The experience {Command line tools} 113 @nisrulz

  113. The experience • APK Analyzer(GUI) 114 @nisrulz

  114. The experience • APK Analyzer(Command line) // To print the

    file size of the apk in a human readable format //Output: 1.7MB 115 @nisrulz
  115. The experience • APK Analyzer // Prints the application ID,

    version code, and version name. // Output: in.excogitation.deviceinfo 17 2.0.1 apkanalyzer apk summary myapp.apk 116 @nisrulz
  116. The experience • APK Analyzer // Prints an estimate of

    the download size of the APK. // Output: 1.4MB apkanalyzer -h apk download-size myapp.apk More info: https://developer.android.com/studio/command-line/apkanalyzer 117 @nisrulz
  117. The experience • APK Analyzer // Get package name of

    the passed apk file // Usage: getPackageName app-debug.apk alias getPackageName="apkanalyzer -h manifest application-id $1" More info: https://developer.android.com/studio/command-line/apkanalyzer 118 @nisrulz
  118. The experience • Size Analyzer // Tool to understand the

    size of Android application. size-analyzer check-bundle <path-to-aab> size-analyzer check-project <path-to-project-directory> More info: https://github.com/android/size-analyzer 119 @nisrulz
  119. The experience • Size Analyzer 120 @nisrulz

  120. The experience • Android Studio Poet // Create a real

    life complexity Android project that // mimics your own and observe the build times java -jar as-poet.jar MyConfig.json More info: https://github.com/android/android-studio-poet 121 @nisrulz
  121. The experience • Android Studio Poet 122 @nisrulz

  122. The experience • Simpleperf A versatile command-line CPU profiling tool

    included in the NDK for Mac, Linux, and Windows. 123 @nisrulz
  123. The experience • Simpleperf # Find the percentage of time

    spent in each thread simpleperf report --sort tid,comm # See how function calls are related, call-graph simpleperf report -g More info: https://developer.android.com/ndk/guides/simpleperf 124 @nisrulz
  124. The experience • NDK-Stack It allows you to symbolize stack

    traces from adb logcat It replaces any address inside a shared library with the corresponding <source-file>:<line-number> from your source code, making debugging easier. 125 @nisrulz
  125. The experience • NDK-Stack # Live mapping adb logcat |

    $NDK/ndk-stack -sym $PROJECT_PATH/obj/local/armeabi-v7a More info: https://developer.android.com/ndk/guides/ndk-stack 126 @nisrulz
  126. The experience • Other tools ◦ NDK-GDB: Tool to start

    a command-line native debugging session. ◦ ASan (Address Sanitizer): Memory error detector for C/C++ 127 @nisrulz
  127. The experience • Other tools ◦ systrace: Tool to collect

    and inspect timing information across all processes running on your device at the system level. ◦ dumpsys: Tool to View the Java heap and memory allocations with Memory Profiler 128 @nisrulz
  128. The experience • Other tools ◦ bundletool: To recreate, inspect,

    and verify Google Play’s server-side build of your app’s APKs. ◦ perfetto: collect performance information from your Android devices via the Android Debug Bridge (ADB) 129 @nisrulz
  129. The experience • Other tools 130 @nisrulz

  130. The experience • Improving on-demand dependency inclusion 131 @nisrulz

  131. The experience … and a lot of cool new things

    the Android Tools team builds 132 @nisrulz
  132. Links/References Gradle Performance Tips: https://guides.gradle.org/performance/ Project Marble: https://medium.com/androiddevelopers/tagged/project-marble Blog Post:

    https://android.jlelse.eu/how-i-reduced-my-android-build-times-by-89-4242e51 ce946 Disable Plugins: https://www.reddit.com/r/androiddev/comments/7sxhig/android_studio_slower_wh en_using_kotlin/dt88pgn/ Battery Historian: https://developer.android.com/studio/profile/battery-historian 133 @nisrulz
  133. Credits Icon made by Freepik from www.flaticon.com 134 @nisrulz

  134. 135 twitter.com/nisrulz github.com/nisrulz www.nisrulz.com

  135. 136 twitter.com/nisrulz github.com/nisrulz www.nisrulz.com