what exactly is "configuration on demand" in Gradle? - android

I recently changed some settings in Gradle to speed up its process and one of them was changing this: org.gradle.configureondemand=true property in gradle.properties file.
I know you can guess a lot from the words "configuration on demand", but I wanna know the exact impact of this feature? Do I have to do something to trigger configuration if I set this argument as true?
Can something go wrong if I set it as true ?
What configuration phase exactly is?

This setting is relevant only for multiple modules projects. Basically, it tells Gradle to configure modules that only are relevant to the requested tasks instead of configuring all of them, which is a default behaviour.
To answer more precisely to your questions:
No, you don't have to trigger configuration manually.
Yes, something could go wrong as stated in the documentation. The
feature should work very well for multi-project builds that have
decoupled projects.
In “configuration on demand” mode, projects are configured as follows:
The root project is always configured. This way the typical common configuration is supported (allprojects or subprojects script blocks).
The project in the directory where the build is executed is also configured, but only when Gradle is executed without any tasks. This way the default tasks behave correctly when projects are configured on demand.
The standard project dependencies are supported and makes relevant projects configured. If project A has a compile dependency on project B then building A causes configuration of both projects.
The task dependencies declared via task path are supported and cause relevant projects to be configured. Example: someTask.dependsOn(:someOtherProject:someOtherTask)
A task requested via task path from the command line (or Tooling API) causes the relevant project to be configured. For example, building projectA:projectB:someTask causes configuration of projectB.
Here is the full documentation.

Related

Android studio is slow in gradle building

Android studio is getting slow in grade building process.I noticed this problem after updating to new version 3.5.Is there any ways to
speed up the building process?
1- Make sure you’re using the latest version of Gradle. Generally with every new update there is a significant improvement in performance.
Note: Java 1.8 is faster than 1.6. Make sure it’s updated too.
2- Try to minimize the use of modules. There are many cases where we need to fork the library to modify it to fit according to our needs. A module takes 4x greater time than a jar or aar dependency. This happens due to the fact that the module needs to be built from the scratch every time.
3- Enable gradle Offline Work from Preferences-> Build, Execution, Deployment-> Build Tools-> Gradle. This will not allow the gradle to access the network during build and force it to resolve the dependencies from the cache itself.
Note: This only works if all the dependencies are downloaded and
stored in the cache once. If you need to modify or add a new
dependency you’ll have to disable this option else the build would
fail.
4-Open up the gradle.properties file from the root of your project. Add the following lines of code in it.
org.gradle.daemon=true
Gradle daemon is a background process. Adding this would consume some extra memory while building.
org.gradle.parallel=true
The above line of code enables compilation of multiple modules at the same time. Besides that it also gives us other benefits such as;
Re-using the configuration for unchanged projects
Project-level is up-to-date checks
Using pre-built artifacts in the place of building dependent projects
Adding the following line of code also aids us in speeding up the build.
org.gradle.configureondemand=true
Another important property is;
org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
The above line is used to allow Java compilers to have available memory up to 2 GB (2048 MB). It should only be used if you have available memory more than 2 GB.
This is how the gradle.properties file should look like:
5- Avoid dynamic dependencies such as
compile 'com.google.maps.android:android-maps-utils:0.4+'.
Dynamic Dependencies slow down your build since they keep searching for the latest builds every time. To improve the performance we need to fix the version in place.
6- Use only those dependencies that you need. For example google maps dependency, instead of importing , like :
implementation 'com.google.android.gms:play-services:17.0.0'
implementation 'com.google.android.gms:play-services-maps:17.0.0'
Gradle build speed depends on a lot of factors including the specification of your machine as well as your build type and android studio settings. You can check out this article on how to reduce your build time or go through the steps in the Android developer website.
Personal experience:
When I faced this issue, enabling offline mode drastically reduced my build time. The only problem is that I have to toggle this setting (on and off) every time I want to add a new dependency and this almost made me go berserk on several occasions. However, if properly handled, this helps a great deal.
I hope this helps. Merry coding!
you can set file->setting->search 'Gradle'-> check 'use local gradle distribution' and check 'offline work'.. in android studio. it will improve gradel building time.
Note: In newer version of Android studio, View->Tool Windows->Gradle->Toggle button of online/offline

Composite Builds in Android Studio

I am looking to use Gradle's new composite build feature in an Android Studio project called MyProject that includes both an Android Archive library (.aar) called DroidLib and a Java library (.jar) called JavaLib. These libraries are currently checked into version control due to my inability to get Gradle to pull dependencies from our internal Artifactory. That is, the DroidLib project has the JavaLib.jar checked into git under the libs folder and the MyProject project has the DroidLib.aar checked into git under its libs folder. I would like to make changes in both DroidLib & JavaLib while debugging and consuming the changes in MyProject w/o manually rebuilding from the dependency projects.
The new Composite build feature in Gradle offers just the thing I need however it looks to be something triggered from the command-line via a flag such like this:
--include-build ../DroidLib
In the Gradle docs it looks like this flag allows Gradle to override a dependency declared in the local project with a similarly the project declared in the included build. This would make sense since they both would use the same group/name/version scheme. I'm having trouble trying to understand how I would use this from Android Studio where my DroidLib dependency is declared as a local filesystem based dependency:
compile(name:'DroidLib-1.19', ext:'aar')
How would the command line flag tell Gradle which dependency is overridden since there is no apparent group/name/version declared on DroidLib? Also how could I make use of this in my app launch run config which uses the Gradle-aware make feature? Is there a way to pass add'l options to the Gradle-aware make or am I over-thinking what has to happen here?
Short answer
It is not available yet (it is in IntelliJ 2016.3).
More details
According to this blog post, the feature is in IntelliJ 2016.3:
With composite builds, everything is much, much simpler. All you have to is to attach the Gradle projects of these libraries via the Add button in the Gradle tool window (my-utils in our case), and then select Compose Build Configuration from the context menu for the original project.
Unfortunately, according to this release note, Android-Studio 2.3 is based on IntelliJ 2016.2. So we'll have to wait for IntelliJ 2016.3 to be merged into Android Studio =/.

How to know which project is running in gradle

I have multiple projects and one trunk...
Some times I need to run via cmd:
gradlew Proj1:assembleRelease
And other times:
gradlew Proj2:assembleRelease
How can I in gradle file know what is building Proj1 or Proj2?
You can access this information via the gradle property on any instance of Project. From the docs:
getGradle()
Returns the Gradle invocation which this project belongs to.
The instance of Gradle provides the startParameter property, which contains the information you want. For example, in the root scope:
print project.gradle.startParameter
For my particular invocation, I could print the name of the first task request via
print project.gradle.startParameter.taskRequests[0].args[0]
However, the above is probably quite fragile and will surely fail in a number of important cases.
There are also many other things you may find useful in the Gradle instance, if the above doesn't do exactly what you want, such as the task execution graph and root project for this build. Note that all the above information is available by following links from the documentation for the Project class, which I linked above. I strongly recommend that you peruse this documentation.
On the other hand, why do you want to do this? Usually you would just add configuration to the individual projects themselves and let the task runner take care of running your specific implementations, rather than saying if task1 is running then x else y

How do I use this file from Github on Android Studio?

I understand this might be an extremely obvious and ridiculous question to ask, but please excuse me as I'm a beginner. I want to integrate this file into my project so I can call its methods:
https://github.com/RomainPiel/Shimmer-android
The question is, what do I do with it? Is it considered a "module", "library" or "file"? Should I manually copy the source files and create new classes in my project, and then call the methods from there? This would be the most straight-forward but in the "how to use" section in that package, it was mentioned "compile 'com.romainpiel.shimmer:library:1.4.0#aar'"
What I tried:
I downloaded the file as a .zip and then File->New->Import Module then navigated to the unzipped file. I believe I'm then supposed to add "compile 'com.romainpiel.shimmer:library:1.4.0#aar'" so I went to the gradle file to try to add it.
There are two: build.gradle (Module:app) and (Project:ProjectName).
I've tried adding to either and\or both and got this error: (Error:9,0) The project 'ProjectName' may be using a version of Gradle that does not contain the method. Did I do something wrong? Is it supposed to be this easy?
I would be extremely grateful to anyone who can point me in the right direction :)
You have three option
Using the GitHub Desktop you can clone the project and open it like a local project. Every change you make will be tracked. You can then commit and push using the GitHub Desktop. It's all UI and simple to use.
https://desktop.github.com
On Android Studio, when you open it, you'll see this, select GitHub and continue by adding your credentials.
You can then commit and push directly from that.
Using the terminal / command line.
If you are new, I recommend the first. It's simple to use and you get a hang of using it as it is the same steps with any project on any IDE you use.
Note: Downloading it as zip and then using it a bad idea because you're making it difficult on yourself because you can't keep track of changes and you'll have to re-upload everything every time. Which defeats the purpose of version control
If that GitHub account is not yours, then you'll have to fork the project, this way you'll have a separate version of the code on you GitHub on which you can modify. If it is yours then you're good.
Typically, you do not want to include external source code manually. This inhibits your build tool's (i.e. Gradle's) ability to manage that source code. It's very easy in Gradle to, say, set the version (like you have done by specifying "1.4.0") and then later remind yourself what version you have by merely looking at your build.gradle file. However, how would you go about doing that with raw source code? Typically developers do NOT put the version number of the source code in the actual source code - that's what they use their version control system (e.g. git) for, usually with tags.
Another aspect of Gradle is downloading and caching (and compiling) the external project for you. So that's nice.
With that said, you typically want to put that "compile..." line in your module's build.gradle file. Not the Project's build.gradle.
A module corresponds to your application (or library) that you are building or using. Some project's have multi-module configurations, where one module acts as a dependency for another (or several others). A Project in gradle is more of a 'meta' configuration that you can apply to all of your modules. The gradle docs recommend you focus on your module's configuration first and adjust the Project's configuration only if you have a specific need and reason to do so.
For the error you mentioned, you might have some unnecessary configurations in your build.gradle file, or the tool version numbers might not reflect what's on your system - if you copied and pasted from the internet, you might want to correct this by letting your IDE generate that file (the brute-force approach would be to create a new project entirely, and use its build.gradle files as a reference). Before you do that, you might want to check if your IDE provides any warnings inside that file.
You have to add the dependency to your module's gradle file.
There are two gradle file present in an android project. One is the project gradle and the second is the module gradle for each individual module.
You just have to copy the given
compile '......' in the dependency block.

In a multi-project setup, Gradle evaluates EVERY sub-project. Can I ignore some of the subprojects?

I have the following multi-project setup in Gradle for building multiple Android apps which use a few libraries:
Let's say my root dir is /workspace
The directory structure is the following (it's incomplete):
/workspace/ --> root dir for the gradle build
/workspace/settings.gradle
...
/workspace/myapp1/Android/ --> contains the 1st app (has a build.gradle)
/workspace/myapp2/Android/ --> contains the 2nd app (has a build.gradle)
...
/market_licensing/library/ ---> contains a lib (has a build.gradle)
/play_apk_expansion/downloader_library/ ---> another lib (has a build.gradle)
settings.gradle in /workspace/ looks like this:
include ':market_licensing:library'
include ':play_apk_expansion:downloader_library'
include ':myapp1:Android'
include ':myapp2:Android'
When I run a gradle build in one of the app directories, it works:
For example, /workspace/myapp1/Android>gradle clean runs fine.
However, this will EVALUATE also the build.gradle project for myapp2.
This is expected according to the Gradle manual. In http://www.gradle.org/docs/current/userguide/multi_project_builds.html, in part 56.3. Execution rules for multi-project builds it says "Gradle always evaluates every project of the multi-project build and creates all existing task objects.".
My problem with this is that this slows down my builds unnecessarily. Unnecessarily because, when I'm building myapp1, I don't care about myapp2. I want the libraries to be in a good state, but I don't care about myapp2. This is not terrible for 2 apps, but imagine having 20 apps. I want to be able to build the app that I'm currently working on as fast as possible.
Is there a way to ignore other subprojects , even for the evaluation stage?
Or is there an alternative way to set up multiple projects that depend on the same libraries but don't depend on each other?
as you pointed out the default behaviour in gradle is to evaluate all projects. There are plans (and also initial work started) to make this more fine grained in the future. For now you might checkout the incubating feature "configuration on demand". Maybe this helps you. have a look at http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:cross_project_configuration for details
cheers,
René

Categories

Resources