My application has a bunch of librarys that are essential that is why I was forced to use multidex support library and it works nicely. But where the problem shows is in the gradle buid speed. It takes on average 2minutes to build and when I am developing and testing this is quite annoying.
Is there a way to speed up my debug builds?
You can speed-up your development builds by specifying the minimum SDK version = 21.
Official documentation includes a whole section about that.
Example (from documentation):
android {
productFlavors {
// Define separate dev and prod product flavors.
dev {
// dev utilizes minSDKVersion = 21 to allow the Android gradle plugin
// to pre-dex each module and produce an APK that can be tested on
// Android Lollipop without time consuming dex merging processes.
minSdkVersion 21
}
prod {
// The actual minSdkVersion for the application.
minSdkVersion 14
}
}
...
buildTypes {
release {
runProguard true
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
}
}
}
dependencies {
compile 'com.android.support:multidex:1.0.0'
}
Once you added the product flavors, you can use the devDebug task (instead of default debug task) for your development builds:
- from command line: run ./gradlew installDevDebug
- from Android Studio: open Build Variants window and select the devDebug build variant.
You should, of course, work against a device whose SDK >= 21.
There's also a solution for those who don't want to use flavors. As suggested in this gist, dynamically calculate the minSdkVersion value:
int minSdk = hasProperty('devMinSdk') ? devMinSdk.toInteger() : 14
apply plugin: 'com.android.application'
android {
...
defaultConfig {
minSdkVersion minSdk
...
}
}
In this example, we're checking if devMinSdk property defined, and if true - we're using it. Otherwise, we default to 14.
How do we pass devMinSdk value to build script? Two options:
Using command line:
./gradlew installDebug -PdevMinSdk=21
Using Android Studio preferences:
Go to Preferences (Settings on Windows) -> Build, Execution, Deployment -> Compiler -> put -PdevMinSdk=21 in Command-line Options text box.
Recently build cache was introduced by team working on Android Gradle plugin. You can enable it by adding android.enableBuildCache=true to gradle.properties.
More info here
http://tools.android.com/tech-docs/build-cache
For me it increased incremental build times by ~30 seconds.
It doesn't work with legacy multidex (com.android.support:multidex) introduced as part of support library, so it's suitable only if your minSDK >= 21. You can set it only for your your development builds and do release builds with minSDK < 21.
It also works without multidexing enabled.
Android Studio 1.3 (currently in Preview 3) is using a new build system which improved gradle build time (really, like 10-30x faster).
More information in the Live Session at Google I/O 2015
Multidexing uses more memory. As you get closer to your max heap size in Java you'll find Java spends more time doing GC than it does doing any real work, this can slow things down a lot.
I'd strongly recommend increasing the max heap size when using multidex. Add the following to the android closure in your build.gradle file to make the max heap size 4GB (Make it smaller if you wish):
dexOptions {
javaMaxHeapSize "4g"
}
Changing MinSdk to 21 made everything back to normal for me.Now everything compiles in like 6s
This is no longer needed with the latest Android Studio 3.0
Go in setting , search compiler , type "--offline" in Command line options and than compile.
Related
My android build is set to use a versionName and versionCode from a file in release mode. They are set to static values when not creating a release build to keep incremental builds working.
The relevant parts of the gradle file are:
android {
defaultConfig {
versionCode 1
versionName "1.0"
// SNIP...
}
applicationVariants.all { variant ->
if (variant.buildType.name == "release") {
variant.versionCode = file('version-code.txt').text as int
variant.versionName = file('version.txt').text
}
}
// SNIP ...
}
Example contents of the version files could be:
version.txt: 0.7
version-code.txt: 7
This was done by following the Use static build config values with your debug build section in the recommended guidelines for keeping incremental builds working.
For example, using dynamic version codes, version names, resources, or any other build logic that changes the manifest file requires a full APK build every time you want to run a change—even though the actual change might otherwise require only a hot swap. If your build configuration requires such dynamic properties, then isolate them to your release build variants and keep the values static for your debug builds, as shown in the build.gradle file below.
However, we've found this has broken since upgrading to version 3 of the gradle plugin this no longer works. The Modifying variant outputs at build time may not work section of the gradle plugin 3.0.0 migration guide says:
Using the Variant API to manipulate variant outputs is broken with the new plugin. It still works for simple tasks, such as changing the APK name during build time, as shown below:
However, more complicated tasks that involve accessing outputFile objects no longer work. That's because variant-specific tasks are no longer created during the configuration stage. This results in the plugin not knowing all of its outputs up front, but it also means faster configuration times.
There doesn't seem to be any alternative recommended in the migration guide. Is there another way this can be achieved?
UPDATE
Thanks to the answer from #nhoxbypass, changing my gradle file to contain following got things working again:
applicationVariants.all { variant ->
if (variant.buildType.name == "release") {
variant.outputs.all { output ->
output.setVersionNameOverride(file('version.txt').text)
output.setVersionCodeOverride(file('version-code.txt').text as int)
}
}
}
The migration guide still works for simple tasks, such as changing the APK name during build time (at least worked for my project). However, more complicated tasks that involve accessing outputFile objects no longer work.
But if you need to try a workaround there is one existing before the 3.0 release, if anybody is looking for a solution, you can use:
output.setVersionCodeOverride(Integer.parseInt(buildTimeSmall()))
See: Unable to change project versionCode for different build types
This is my productFlavors definition in build.gradle:
flavorDimensions "fasterbuild", "flavor"
productFlavors {
slow {
dimension "fasterbuild"
// "Slow" uses the defaultConfig minSdkVersion, currently 16
}
fast {
dimension "fasterbuild"
//Use minSdk 21, mainly to avoid legacy multidex
minSdkVersion 21
//Crashlytics will generate a new build id for every build.
//This can (and should) be disabled for debug builds with a single line:
ext.alwaysUpdateBuildId = false
}
dev {
dimension "flavor"
...
}
market {
dimension "flavor"
...
}
}
This produces the following buildVariants:
(I filter out the fastMarket* combinations).
Problem
Based on the above definition, I expect Crashlytics' alwaysUpdateBuildId setting to be disabled only in fast* variants.
However, when running assembleSlowDevDebug, I still see the following:
Detected alwaysUpdateBuildId set to false while obfuscation is enabled. This may result in obfuscated stack traces in Crashlytics.
Here's more of the gradle ouput:
Executing tasks: [:app:assembleSlowDevDebug]
Configuration on demand is an incubating feature.
NDK is missing a "platforms" directory.
If you are using NDK, verify the ndk.dir is set to a valid NDK directory. It is currently set to /Users/aphex/Library/Android/sdk/ndk-bundle.
If you are not using NDK, unset the NDK variable from ANDROID_NDK_HOME or local.properties to remove this warning.
NDK is missing a "platforms" directory.
If you are using NDK, verify the ndk.dir is set to a valid NDK directory. It is currently set to /Users/aphex/Library/Android/sdk/ndk-bundle.
If you are not using NDK, unset the NDK variable from ANDROID_NDK_HOME or local.properties to remove this warning.
Jack is disabled, but one of the plugins you are using supports Java 8 language features.
Jack is disabled, but one of the plugins you are using supports Java 8 language features.
Jack is disabled, but one of the plugins you are using supports Java 8 language features.
Jack is disabled, but one of the plugins you are using supports Java 8 language features.
Jack is disabled, but one of the plugins you are using supports Java 8 language features.
Jack is disabled, but one of the plugins you are using supports Java 8 language features.
The Task.leftShift(Closure) method has been deprecated and is scheduled to be removed in Gradle 5.0. Please use Task.doLast(Action) instead.
Detected alwaysUpdateBuildId set to false while obfuscation is enabled. This may result in obfuscated stack traces in Crashlytics.
Build cache is an incubating feature.
Using directory (/Users/aphex/.gradle/caches/build-cache-1) as local build cache, push is enabled.
:app:preBuild UP-TO-DATE
:app:preSlowDevDebugBuild UP-TO-DATE
...
I've further confirmed this erroneous behavior by completely removing the ext.alwaysUpdateBuildId = false line from the fast variant and re-running assembleSlowDevDebug. The offending Detected alwaysUpdateBuildId set to false line disappears.
Question
This doesn't make any sense based on my understanding of build variants and product flavors. Is this a Gradle bug, Crashlytics/Fabric issue, or both? I'm using Gradle 3.5 and the Android tools gradle plugin 2.3.3.
Here is the thing. I have an app that is compatible with API 15 and above, but since it's pretty big and I've already hit a 65k methods limit, I had to make it a descendant of MultiDexApplication class.
This slows down the build times a bit, so I had to implement some optimization to speed up the process. I have the following code in my manifest, which significantly reduce build times when building for API >= 21 (taken from some other SO thread):
productFlavors {
dev {
minSdkVersion 21
}
prod {
minSdkVersion 15
}
}
Everything is working perfectly, but the problem is that during the development, Android studio thinks that my minSdkVersion SDK level is 21 (correctly), and the lint does not show me incompatible API (15-21).
What I really want is to be able to build with minSdkVersion set to 21 (fast build), but set the "lint minSdkVersion" to 15, so I see the parts of the code that are not compatible with older API than 21.
I tried to google it and also to look into AS lint preferences but I didn't find anything useful. Thanks for any suggestions. My current solution is to switch minSdkVersion in dev flavor to 21 and check if there's any error, but this is not really what I want.
This gist answers your question. It shows how to build the project with whatever dev minimum SDK value, while maintaining production minimum SDK value for Lint warnings.
To summarize the post, you can dynamically calculate the minSdkVersion value:
int minSdk = hasProperty('devMinSdk') ? devMinSdk.toInteger() : 15
apply plugin: 'com.android.application'
android {
...
defaultConfig {
minSdkVersion minSdk
...
}
}
In this example, we're checking if devMinSdk property defined, and if true - we're using it. Otherwise, we default to 15.
How do we pass devMinSdk value to build script? Two options:
Using command line:
./gradlew installDebug -PdevMinSdk=21
Using Android Studio preferences:
Go to Preferences (Settings on Windows) -> Build, Execution, Deployment -> Compiler -> put -PdevMinSdk=21 in Command-line Options text box.
I am trying to build Multidex apk in eclipse, and not able to succeed.
I tried following steps, for configuring Multidex support in android app:
I have added the Multidex library located at /extras/android/support/multidex/ to my project.
As my app is having custom application class, I have extended android.support.multidex.MultiDexApplication Class to my application.
Still i am not able to build apk.
Android developer is also not having any documentation for building Multidex apk in eclipse, its only having documentation for gradle and Android Studio.
You have to modify build.gradle to add multiDexEnabled true under buildconfig, buildType or productFlavour sections
defaultConfig {
// The support library goes as back as Android-14, and is not required for 21+
minSdkVersion 14
// Enabling multidex support.
multiDexEnabled true
}
If you're building on old Ant, this is a blocking problem so you'll have to move to gradle or maven or use the old cumbersome solution
http://android-developers.blogspot.com.es/2011/07/custom-class-loading-in-dalvik.html
I have 5 modules in my project, it takes me 2 mins to build everytime, is there any way to speed up android studio build time?
You can try to add this in your build.gradle file inside the android closure
dexOptions {
incremental true
javaMaxHeapSize "4g"
}
It will allocate large heap size for your dex process which usually takes more time in build.
You can change your your heap size according to RAM you have in your system like "2048M" for 2GB allocation.
Another idea might be using a faster repository. If your build is using mavenCentral() try to replace it with jcenter().
For me, adding the following two properties to the "gradle.properties" file in the project root improved performance considerably.
org.gradle.parallel=true
org.gradle.daemon=true
"org.gradle.parallel=true" does parallel processing of the modules. You may receive a message that the feature is experimental but it has worked for me without any problems.
"org.gradle.daemon=true" will keep a dedicated Gradle JVM running so that it is not re-started each time you do a build. This first build takes as long but subsequent builds are much quicker.
Hope this helps.
Yup you can speed up android studio build time.
1. You need to clean your project before building your project.
2. Close all other projects on which you are not working before build.
3. Allow auto build option.
According to this document https://developer.android.com/studio/build/multidex.html#dev-build
If you are using MultiDexApplication you can set minSdkVersion 21 for your develop productFlavors to mitigate the longer build times for multidex output.
productFlavors {
dev {
// Enable pre-dexing to produce an APK that can be tested on
// Android 5.0+ without the time-consuming DEX build processes.
minSdkVersion 21
}
prod {
// The actual minSdkVersion for the production version.
minSdkVersion 14
}
}