What happened
● Trying to build an Android Project
○ Typical project
○ Multi module
4
@nisrulz
Slide 5
Slide 5 text
What happened
● Trying to build an Android Project
○ Native code (NDK)
○ Common dependencies:
Retrofit, Dagger, Rx, Support
Libraries, etc
5
@nisrulz
Slide 6
Slide 6 text
What happened
● Laptop: Macbook Air (early 2014)
○ Core i5(1.4 Ghz)
○ 4GB DDR3 RAM
○ 128GB SSD
○ Intel HD Graphics (1.5GB)
6
@nisrulz
Slide 7
Slide 7 text
What happened
My build times: ~37 min
7
@nisrulz
Slide 8
Slide 8 text
What happened
My build times: ~37 min
Not just the first time, but every
other build after that too
8
@nisrulz
Slide 9
Slide 9 text
What happened
My build times: ~37 min
…and not only that
9
@nisrulz
Slide 10
Slide 10 text
What happened
...but also
10
@nisrulz
Slide 11
Slide 11 text
What happened
With a few gradle tweaks in the
project.
11
@nisrulz
https://guides.gradle.org/performance/
Slide 12
Slide 12 text
What happened
Build times down to ~28 min
With a few gradle tweaks in the
project.
12
@nisrulz
https://guides.gradle.org/performance/
Slide 13
Slide 13 text
What happened
13
@nisrulz
After exhausting all possibilities.
Slide 14
Slide 14 text
What happened
Switched to Terminal builds and
VS Code Editor.
14
@nisrulz
+
After exhausting all possibilities.
Slide 15
Slide 15 text
What happened
15
@nisrulz
+
Slide 16
Slide 16 text
What happened
16
@nisrulz
+
Final result.
Slide 17
Slide 17 text
What happened
17
@nisrulz
+
Build times down to ~3
minutes(89% reduction)
Final result.
Slide 18
Slide 18 text
18
@nisrulz
How I reduced my Android build times by 89%
Slide 19
Slide 19 text
19
@nisrulz
I was just happy that I was not in a
spot like this guy
Slide 20
Slide 20 text
The experience.
@nisrulz 20
Slide 21
Slide 21 text
The experience
State of speed: Slow
21
@nisrulz
Slide 22
Slide 22 text
The experience
Basically this...
State of speed: Slow
22
@nisrulz
Slide 23
Slide 23 text
The experience
State of speed: Slow
23
@nisrulz
Slide 24
Slide 24 text
The experience
State of reliability: Critical issues
24
@nisrulz
Slide 25
Slide 25 text
The experience
State of reliability: Critical issues
25
@nisrulz
https://issuetracker.google.com/issues/133864394
Slide 26
Slide 26 text
The experience
State of reliability: Critical issues
26
@nisrulz
https://issuetracker.google.com/issues/133864394
Slide 27
Slide 27 text
The experience
State of reliability: Critical issues
27
@nisrulz
~3 months
https://issuetracker.google.com/issues/133864394
Slide 28
Slide 28 text
The experience
State of reliability: Finicky
28
@nisrulz
Slide 29
Slide 29 text
The experience
State of reliability: Finicky
29
@nisrulz
Slide 30
Slide 30 text
The experience
To a point where someone had to
build this:
A nuke script!
https://github.com/rock3r/deep-clean
30
@nisrulz
Slide 31
Slide 31 text
The experience
- Tweet dated: 26 July 2019
- Android Studio 3.5 Stable
(released): 20 August 2019
> Was already on bleeding edge
31
@nisrulz
https://twitter.com/nisrulz/status/1154760
114026532864
Slide 32
Slide 32 text
The experience
32
@nisrulz
https://twitter.com/nisrulz/status/1154758411684392961
Slide 33
Slide 33 text
The experience
State of polish:
33
@nisrulz
https://www.reddit.com/r/androiddev/c
omments/d271hc/wildly_infuriating/
Slide 34
Slide 34 text
The experience
State of choice: Forced, deviates from base
34
@nisrulz
Slide 35
Slide 35 text
The experience
State of memory consumption: Not suitable
35
@nisrulz
Slide 36
Slide 36 text
The experience
State of memory consumption: Not suitable
36
@nisrulz
Slide 37
Slide 37 text
The experience
State of memory consumption: Not suitable
37
@nisrulz
Slide 38
Slide 38 text
The experience
State of CPU consumption: Unacceptable
38
@nisrulz
Slide 39
Slide 39 text
The experience
State of CPU consumption: Unacceptable
39
@nisrulz
Slide 40
Slide 40 text
The experience
State of updates: Unreliable
40
@nisrulz
Slide 41
Slide 41 text
The experience
State of result: false-positives
41
@nisrulz
Slide 42
Slide 42 text
The experience
State of result: false-positives
42
@nisrulz
Slide 43
Slide 43 text
The experience
State of tools: Limited
43
@nisrulz
Energy Profiler
Slide 44
Slide 44 text
The experience
State of tools: Limited
44
@nisrulz
Constraint Layout Editor
Slide 45
Slide 45 text
The experience
State of tools: Limited
45
@nisrulz
Resource Manager
Slide 46
Slide 46 text
The experience
State of tools: Limited
46
@nisrulz
Apply Changes
Slide 47
Slide 47 text
The experience
State of tools: Limited
47
@nisrulz
Apply Changes
https://medium.com/androiddevelopers/android-studio-pro
ject-marble-apply-changes-e3048662e8cd
Slide 48
Slide 48 text
The experience
State of tools: Limited
48
@nisrulz
Apply Changes
https://developer.android.com/studio/known-issues#appl
y-changes-ki-verification-errors
Slide 49
Slide 49 text
The experience
State of tools: Limited
49
@nisrulz
Deployments
Slide 50
Slide 50 text
The experience
To summarize, Android Studio is
● Slow
● Finicky
● Forces its defaults and deviates from its base
50
@nisrulz
Slide 51
Slide 51 text
The experience
To summarize, Android Studio is
● New tools are limiting
○ Energy Profiler
○ Constraint Layout Editor
○ Resource Manager
○ Apply Changes
○ Deployments options
51
@nisrulz
Slide 52
Slide 52 text
The experience
To summarize, Android Studio is
● Uses a lot of Memory and CPU
● Has versioning quality problem
(Stable, Beta, Alpha)
52
@nisrulz
Slide 53
Slide 53 text
and Workarounds.
@nisrulz 53
Slide 54
Slide 54 text
Slow, but why?
● Gradle Configuration
● Indexing changes in code
● Plugins
● Code Insight: Inplace analysis/inspections
54
@nisrulz
Slide 55
Slide 55 text
Configuring Gradle for speed
Use the latest Gradle release.
55
@nisrulz
Incremental compile 1000-module Java project
https://gradle.org/whats-new/gradle-5/
Slide 56
Slide 56 text
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.
56
@nisrulz
Slide 57
Slide 57 text
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
57
@nisrulz
Slide 58
Slide 58 text
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
58
@nisrulz
Slide 59
Slide 59 text
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
59
@nisrulz
Slide 60
Slide 60 text
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
60
@nisrulz
Slide 61
Slide 61 text
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
61
@nisrulz
Slide 62
Slide 62 text
Reducing Indexing
If your codebase has files changing on each build, it
will trigger indexing.
62
@nisrulz
Slide 63
Slide 63 text
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
63
@nisrulz
Slide 64
Slide 64 text
Plugins: Inspect what you use
Android Studio comes with a lot of Plugins enabled,
which contribute to its sluggishness.
64
@nisrulz
Slide 65
Slide 65 text
Plugins: Inspect what you use
Solution:
Check and disable what you don’t need.
65
@nisrulz
Slide 66
Slide 66 text
Code Insight
Although required, it does make Android Studio slow.
Solution:
Enable Power Save Mode
66
@nisrulz
Slide 67
Slide 67 text
Terminal to the rescue.
@nisrulz 67
Slide 68
Slide 68 text
ADB: Android Debug Bridge
● Command Line tool
● Shipped with Android SDK
● Allows interacting with debuggable Android devices
● Client-Server program
● Available as: adb
68
@nisrulz
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/
70
@nisrulz
Slide 71
Slide 71 text
Other tools via ADB shell
● Activity Manager: am
● Emulator: emulator
● Package Manager: pm
● Device Policy Manager: dpm
● Logcat: logcat
● Dumpsys: dumpsys
...and many more.
71
@nisrulz
Slide 72
Slide 72 text
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
72
@nisrulz
Slide 73
Slide 73 text
Gradle
The same can be done via terminal:
./gradlew assembleDebug
> is equivalent to Make in Android studio
73
@nisrulz
Slide 74
Slide 74 text
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
74
@nisrulz
Slide 75
Slide 75 text
Lint
75
@nisrulz
Slide 76
Slide 76 text
Detekt
https://github.com/arturbosch/detekt
● Static code analyzer for Kotlin language.
● Helps to detect code smell in kotlin codebase
76
@nisrulz
Slide 77
Slide 77 text
Detekt
https://github.com/arturbosch/detekt
● Highly configurable
● Enables complexity analysis of the code
● Also has a gradle plugin to setup in the project
77
@nisrulz
Slide 78
Slide 78 text
Detekt
https://github.com/arturbosch/detekt
// Execute at the root of the project
java -jar /path_to/detekt-cli.jar --debug
78
@nisrulz
Slide 79
Slide 79 text
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
79
@nisrulz
Slide 80
Slide 80 text
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.
80
@nisrulz
AVD Manager
● Command line tool to create and manage Android
Virtual Devices (AVD)
● Located in android_sdk/tools/bin/
84
@nisrulz
Slide 85
Slide 85 text
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
85
@nisrulz
Slide 86
Slide 86 text
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
86
@nisrulz
Slide 87
Slide 87 text
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
87
@nisrulz
Slide 88
Slide 88 text
SDK Manager
● Command line tool to manage Android SDK
● Used to view, install, remove packages in Android
SDK
● Located in android_sdk/tools/bin/
88
@nisrulz
Slide 89
Slide 89 text
SDK Manager
// List all available packages
sdkmanager --list
// Install packages
sdkmanager packages
// Remove packages
sdkmanager --uninstall packages
// Update all packages
sdkmanager --update
89
@nisrulz
Slide 90
Slide 90 text
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
90
@nisrulz
Slide 91
Slide 91 text
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.
91
@nisrulz
Slide 92
Slide 92 text
Battery Historian
92
@nisrulz
Slide 93
Slide 93 text
Battery Historian
93
@nisrulz
Slide 94
Slide 94 text
IntelliJ Idea
● Android Studio is based on
IntelliJ Idea
○ IntelliJ Idea can be used for
Android Development
● Faster for development
94
@nisrulz
Slide 95
Slide 95 text
IntelliJ Idea
● Consumes less memory/CPU than
Android Studio
● Full plugin support
● More frequent updates
95
@nisrulz
Slide 96
Slide 96 text
IntelliJ Idea
● Doesn’t have the Android Studio
specific tools
○ Constraint Layout Editor
○ Profilers
○ Resource Manager
○ Apply Changes
96
@nisrulz
Slide 97
Slide 97 text
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
97
@nisrulz
Slide 98
Slide 98 text
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 ↵
98
@nisrulz
Slide 99
Slide 99 text
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"
99
@nisrulz
Slide 100
Slide 100 text
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'
100
@nisrulz
Slide 101
Slide 101 text
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;
}
101
@nisrulz
Slide 102
Slide 102 text
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"
102
@nisrulz
Slide 103
Slide 103 text
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
103
@nisrulz
Slide 104
Slide 104 text
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 is the equivalent of ./adb -s
#
# Examples
# ./adbe version
./adbe install demo_app.apk
104
@nisrulz
https://github.com/nisrulz/terminal-utils/blob/master/android/adbe.sh
Slide 105
Slide 105 text
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
105
@nisrulz
Slide 106
Slide 106 text
Automation
● Use gradle plugin to setup all the automation commands
Some commands available:
● installDevice - installs the app on a specific device.
● uninstallDevice - uninstalls the app from a specific device.
● run - installs and launches the app on a specific device.
and many more.
Execute: ./gradlew installDeviceDebug
106
@nisrulz
Slide 107
Slide 107 text
The experience.
@nisrulz 107
Slide 108
Slide 108 text
The experience
● Project Marble
Project Marble is a multi-release and focused
effort on making fundamental features of the IDE
rock-solid and polished.
108
@nisrulz
Slide 109
Slide 109 text
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
109
@nisrulz
Slide 110
Slide 110 text
The experience
● Project Marble
Issues: https://developer.android.com/studio/known-issues
110
@nisrulz
Slide 111
Slide 111 text
The experience
● APK Analyzer(GUI)
111
@nisrulz
Slide 112
Slide 112 text
The experience
● APK Analyzer(Command line)
// To print the file size of the apk in a human readable format
//Output: 1.7MB
112
@nisrulz
Slide 113
Slide 113 text
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
113
@nisrulz
Slide 114
Slide 114 text
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
114
@nisrulz
Slide 115
Slide 115 text
The experience
● Simpleperf
A versatile command-line CPU profiling tool included in the NDK
for Mac, Linux, and Windows.
115
@nisrulz
Slide 116
Slide 116 text
The experience
● Simpleperf
# Find the percentage of time spent in object modules
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
116
@nisrulz
Slide 117
Slide 117 text
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 : from your source code,
making debugging easier.
117
@nisrulz
Slide 118
Slide 118 text
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
118
@nisrulz
Slide 119
Slide 119 text
The experience
● Other tools
○ NDK-GDB: Tool to start a command-line native debugging
session.
○ ASan (Address Sanitizer): Memory error detector for C/C++
119
@nisrulz
Slide 120
Slide 120 text
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
120
@nisrulz
Slide 121
Slide 121 text
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)
121
@nisrulz
Slide 122
Slide 122 text
The experience
● Other tools
122
@nisrulz
Slide 123
Slide 123 text
The experience
● Improving on-demand dependency inclusion
123
@nisrulz
Slide 124
Slide 124 text
The experience
● … and a lot of cool new things the Android Tools team builds
124
@nisrulz