Why are there two build.gradle files in an Android Studio project? - android

After having imported an Eclipse project into Android Studio, I see two build.gradle files:
1 - <PROJECT_ROOT>\build.gradle
2 - <PROJECT_ROOT>\app\build.gradle
The first version is shorter, the second version contains definitions for compileSdkVersion, etc.
What is the purpose behind having two separate files? Are there separate build tasks?

<PROJECT_ROOT>\app\build.gradle is specific for app module.
<PROJECT_ROOT>\build.gradle is a "Top-level build file" where you can add configuration options common to all sub-projects/modules.
If you use another module in your project, as a local library you would have another build.gradle file:
<PROJECT_ROOT>\module\build.gradle
For example in your top level file you can specify these common properties:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.3.0'
}
}
ext {
compileSdkVersion = 23
buildToolsVersion = "23.0.1"
}
In your app\build.gradle
apply plugin: 'com.android.application'
repositories {
mavenCentral()
}
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
}

From the official documentation:
Android Studio projects contain a top-level project Gradle build file that allows you to add the configuration options common to all application modules in the project. Each application module also has its own build.gradle file for build settings specific to that module.
Project Build File
<PROJECT_ROOT>\build.gradle or the Project Build File is for the entire project, so it will be used for global project configurations.
A typical Project Build File contains the following:
buildscript which defines:
repositories and
dependencies
Gradle Plugin version
By default, the project-level Gradle file uses buildscript to define the Gradle repositories and dependencies. This allows different projects to use different Gradle versions. Supported repositories include JCenter, Maven Central, or Ivy. This example declares that the build script uses the JCenter repository and a classpath dependency artifact that contains the Android plugin for Gradle version 1.0.1.
Module Build File
<PROJECT_ROOT>\app\build.gradle or the Module Build File is for a specific module so it will be used for specific module level configurations.
A Module Build File contains the following:
android settings
compileSdkVersion
buildToolsVersion
defaultConfig and productFlavors
manifest properties such as applicationId, minSdkVersion, targetSdkVersion, and test information
buildTypes
build properties such as debuggable, ProGuard enabling, debug signing, version name suffix and testinformation
dependencies
You can read the official documentation here:
Projects and modules build settings

Related

How to add a local module as dependency to a project in Android Studio?

How can I add a module of a local project as dependency to another project?
I tried the following:
Add to settings.gradle:
include ':app', ':module'
project(':module').projectDir = new File('/path/to/module')
Add to project build.gradle:
buildscript {
dependencies {
ext { compileSdkVersion = 31; minSdkVersion = 19; targetSdkVersion = 31 }
}
}
Add to app build.gradle:
dependencies {
implementation project (":module")
}
But this fails to build with error:
Build file '/path/to/module/build.gradle' line: 3
A problem occurred evaluating project ':module'.
Plugin with id 'com.some.lib' not found.
I can build the module project without any issues with ./gradlew publishToMavenLocal, but how can I build it automatically as part of the parent project?
The goal is to develop the module and test the changes immediately in an example app.
The way I do it now is publish the module to local maven and let local maven override the dependency in the example app, but I wonder if there is a more direct way that automatically builds the module and where I can even debug-step through the module while testing it in the example app.
Remove the space after colon : on line#2 in settings.gradle
It should be project(':module') but you have written project(': module')

Gradle: classpath dependency not resolved from nested project

I have a multi-project build set-up with gradle that will contain multiple android apps and libraries.
Sample of the project structure:
root (Project Root)
| android
| module1 (Android Application)
| module2 (Android Library)
| ios (in the future)
I want to apply certain gradle plugins only to some subprojects. (Such as the android gradle plugin only to the android subproject)
Therefore I added the classpath dependency in the :android -> build.gradle and the plugin declaration to the two android subproject: :android:module1 -> build.gradle -> apply plugin: 'com.android.application'and:android:module2 -> build.gradle -> apply plugin: 'com.android.library'
The problem is that gradle cannot found the android gradle plugin:
Error:(1, 1) A problem occurred evaluating project ':Shoppr:presentation'.
Plugin with id 'com.android.application' not found.
Also it is not a version problem as in some other questions (Gradle Version 3.1; Android Gradle Plugin Version: 2.2.1) because when defining the classpath dependencies in :root -> build.gradle or :android:moduleX -> build.gradle all is working as expected.
:root -> build.gradle
allprojects {
repositories {
mavenCentral()
jcenter()
}
}
:android -> build.gradle
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.1' <-- Should only be applied for android project
}
}
:android:module1 -> build.gradle
apply plugin: 'com.android.application' --> Plugin with id 'com.android.application' not found.
:android:module2 -> build.gradle
apply plugin: 'com.android.library'
I have seen such folder arrangements especially with google sample projects that include and android folder and also a web folder. What you can try is to import the project using the android folder as the project folder since you may not be using gradle to build Ios and web if you have the two more folders for you project.
So close the project and re-import it using the android folder as the project root, i believe this way, gradle should run fine. My project folder is also like this because i have both web and android project in a single repo but during build with android studio, i use the android folder as the project root for the android.
I had a somewhat similar problem. I went from having an android folder with 3 subtasks to dividing it into 3 folders with subtasks:
| android
| shared
-- generates aar
| device1
-- generates 2 apks
| device2
-- generates 1 apk
| gradle
gradlew.bat
gradlew
Both device1 and device2 want to use shared. So I removed settings.gradle and build.grade from the android folder. device1, device2, and shared have their own build.grade and settings.gradle. I build device1 and device2 separately. In order for them to include shared and build, I put symbolic links to shared, gradlew, gradlew.bat, and the gradle folder from the android folder into device1 and device2. And voila, it works! (I'm on an Ubuntu computer, but should be able to do the same on Windows and Mac.)
The disadvantage is that shared is built each time. In our case, that's not too bad, it's not very big.
android gradle [tag:multi-level projects]

Android archive library integration using Maven

I am trying to integrate an Android archive (aar) from local Maven to Android studio in my sample project.
I am getting the following build error in Android studio:
A problem occurred evaluating project :app Could not find property HOME on org.gradle.api.internal.artifacts.repositories.DefaultMavenArtifactRepository_Decorated#181db40.
If you are using local maven to work with android studio you need to do this means that to add a reference to an .aar package it would have to ideally be stored in the central maven repository.
A simple and extremely straightforward option is to create a local maven repository on your dev machine, and install your library in there. Then reference it from your gradle build. And doing it is surprisingly simple!.
Since you're developing for android, I assume you already installed the latest JDK and set the JAVA_HOME environment variable, but if you didn't - now is the time.
Then you'd want to install Maven. You can download it here: http://maven.apache.org/download.cgi
Set the MAVEN_HOME environment variable to the path where you extracted maven, and add the maven's bin folder to the PATH environment variable.
To test that maven is working fine, open a new console window and run the following:
mvn -version
If everything is fine, it's time to add your library to the maven repository. In the command prompt run the following:
mvn install:install-file -Dfile=d:\mylibrary-{version}.aar -DgroupId=com.example -DartifactId=mylibrary -Dversion={version} -Dpackaging=aar
Don't forget to replace the proper path to your library, setting your groupId, artifactId and version number.
Finally, edit your build.gradle to start looking at the local maven repository. For example, if you want to use both maven central and your local repo you can add both of them to the repositories configuration.
Here's an example of a very basic build.gradle for an android app using the library we registered above:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.4.2'
}
}
apply plugin: 'android'
repositories {
mavenCentral()
mavenLocal()
}
dependencies {
compile('com.example:mylibrary:0.2')
}
android {
compileSdkVersion 17
buildToolsVersion '17.0.0'
}
Finally, run the build command to build your app:
gradle clean build.
The main problem is to get the resulting .aar file in the maven publication profile. To do that we'll run a call to android.libraryVariants, which will initialise this object, and create all the subtasks required for the build, including "bundleRelease" which is creating the .aar file.
Here is what my build.gradle file looks like:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.4.2'
}
}
apply plugin: 'android-library'
apply plugin: 'maven-publish'
version '0.2'
group 'com.example'
android {
compileSdkVersion 17
buildToolsVersion '17.0.0'
defaultConfig {
versionCode 2
versionName '0.2'
}
}
android.libraryVariants
publishing {
publications {
maven(MavenPublication) {
artifact bundleRelease
}
}
}
If you want to change the artifactId to something custom, you can change the project name in settings.gradle by adding this line:
rootProject.name = 'mylibrary'
That's it. Now open a command prompt in your project's folder and run the following to build and publish your library to the local maven repository:
gradle clean build publishToMavenLocal
A couple basic articles that I used to get this to work:
How to install maven on windows.
Adding local .aar to gradle build

Android Studio How to build an aar file with gradle that has remote dependencies

I created a Android Library Module with Android Studio and I was able to use it in the apps and right now I need to use it for my other apps. So I was thinking about using the remote dependecies like Picasso https://github.com/square/picasso
compile 'com.squareup.picasso:picasso:2.5.2'
And I would like to know what are the steps I need to take? I read few article and website. It is very confusing.
To make your library available as a remote dependency there are only three steps you have to take:
Build your library and provide the necessary repository meta data
Put your library with meta data in a repository
Tell your project to look in that repository for dependencies
After that is in place you can have remote dependencies like this in your app's build.gradle file:
compile 'com.example.developer:lib-util:1.0.0'
This will look in all the repositories that you have registered for a group or organization called 'com.example.developer', and then an artifact named 'lib-util' with version '1.0.0'.
Build your library and provide the necessary repository meta data
That may sound complex but it's really not that hard. It's just a directory structure that looks a little like this:
com
|-- example
|-- developer
|-- lib-util
|-- 1.0.0
| |-- lib-util-1.0.0.aar
| |-- lib-util-1.0.0.aar.md5
| |-- lib-util-1.0.0.pom
| |-- lib-util-1.0.0.pom.md5
|-- maven-metadata.xml
|-- maven-metadata.xml.md5
The file lib-util-1.0.0.aar is the compiled library (in Android Archive format). The lib-util-1.0.0.pom file contains information about the library itself, such as the authors and its dependencies. The maven-metadata.xml file contains the necessary information to know which versions are available (in this case just one). And lastly the *.md5 files contain a checksum to verify file integrities. (There are also *.sha1 checksum files that I've left out for brevity.)
To build this structure you can make use of the Maven Gradle plugin. Put it in your library's build.gradle and configure the mavenDeployer properties:
library build.gradle:
apply plugin: 'com.android.library'
apply plugin: 'maven'
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
minSdkVersion 16
targetSdkVersion 23
versionCode 1
versionName "1.0.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
uploadArchives {
repositories.mavenDeployer {
pom.groupId = 'com.example.developer'
pom.artifactId = 'lib-util'
pom.version = android.defaultConfig.versionName
// Add other pom properties here if you want (developer details / licenses)
repository(url: "file:./releases/")
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.0.1'
}
The above example is a stock library build.gradle as Android Studio 1.4 produces it for a new library but with the Maven Gradle plugin added and configured.
The second line: apply plugin: 'maven', adds the plugin. The uploadArchives closure configures it.
pom.groupId is the name of the organization/group. This will be written in the .pom file but is primarily used to actually find your library as a remote dependency.
pom.artifactId is the name of your library. Again, this will be put in the .pom file but is used to actually find your lib.
pom.version is the version of your library. You will have to increase this when you make a new release. Also put in the .pom and used to locate your lib.
The line repository(url: "file:./releases/") configures the plugin to write the structure to a filesystem directory relative to the project root.
If you run the following Gradle command in the root directory of your project you should see the Maven directory structure being built.
./gradlew clean uploadArchives
This will first clean your build and then build and perform the uploadArchives task which will create the releases directory.
Put your library with meta data in a repository
You already have a local Maven repository right now, namely on your local filesystem in your lib-util's project directory.
To make it an online remote Maven repository it only has to be reachable by http (or https) get-requests. If you have a server with a webserver like Apache or Nginx or IIS you can configure that to host the files. Or you can check them into your Github account and let that host it. You could even copy those files to Dropbox and use it to host them.
If you want to have it publicly available over Maven Central or JCenter you will have to go to their websites and register for an account where you claim your 'groupId' and you can then use their systems to upload the files so they will be hosted by them.
Tell your project to look in that repository for dependencies
By default Android Studio registers your project to look for dependencies in JCenter. Previously it used to default to Maven Central. So if you have actually uploaded your library to those repositories you wont have to do anything as it will already work.
Suppose you want to configure your project to look for remote dependencies on your local filesystem in /Users/rob/projects/lib-util/releases, and in a self-hosted Maven repository at http://developer.example.com/repo/. Add those repository urls to your project's build.gradle (so not in your library's):
project build.gradle:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.3.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
maven { url '/Users/rob/projects/lib-util/releases/' }
maven { url 'http://developer.example.com/repo/' }
jcenter()
}
}
The example above is the stock project build.gradle as Android Studio provides it with just two extra repositories. Looking dependencies up goes in the order listed. So in this case it first checks the local filesystem, then the self-hosted repo and finally it looks in JCenter.

Two android projects sharing common module in same repository using gradle

We are creating an app (actually 2) that is split up in 2 separate projects but sharing the same GIT repository (2 separate folders in git root). It is one app for handheld and one for another platform. But they should share some code like Utils, API calls etc.
Folder structure looks like this:
-GIT Root
-- Project (Project)
--- App 1 (Android application)
--- App 2 (Android application)
--- Common (Android library)
App1 and App2 should be able to reach code from common but not the other way of course.
Tried to do like above and using Gradle but it doesn't seem to work. I know that sharing the same git repo for both apps may not be the best way to handle this scenario but I'm having no options here.
Do you think that this is possible to do somehow? (Maybe I'm just not understanding modules correctly or something like that)
I'm new to Gradle which makes this even harder..
This is not too hard to do if all three projects are in the same Git repository. Here is the skeleton of how your projects should be setup:
App1 (Android application)
|_ build.gradle
|_ src
App2 (Android application)
|_ build.gradle
|_ src
Common (Android library)
|_ build.gradle
|_ src
settings.gradle
build.gradle
The top-level build.gradle file can have common gradle settings that you will use for all sub-projects
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.0.0'
}
}
allprojects {
repositories {
mavenCentral()
}
}
Make sure the settings.gradle file includes all your projects:
include ':App1'
include ':App2'
include ':Common'
Setup Common to be a Android library project. In the build.gradle file for Common add the line:
apply plugin: 'com.android.library'
Setup the other two projects to be Android applications, and include the Common project as a dependency.
apply plugin: 'com.android.application'
dependencies {
compile project(':Common')
:
:
}
You should have three git repos for this. App1, App2 and Common.
Make common a library project using gradle.
apply plugin: 'com.android.library'
You can use the android maven plugin to build the aar locally and make it available to each child app. Add classpath 'com.github.dcendents:android-maven-plugin:1.2' AND apply plugin: 'com.github.dcendents.android-maven'
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.0.0'
classpath 'com.github.dcendents:android-maven-plugin:1.2'
}
}
apply plugin: 'com.github.dcendents.android-maven'
Define group and version of library app
group = 'com.foo.example'
version = '1.0.0-SNAPSHOT'
Install library app locally using ./gradlew installDebug
Child Apps
Now the parent app can be included in the child app as a dependency. Add dependency to build.gradle.
compile('com.foo.example:library:1.0.0-SNAPSHOT#aar') {transitive = true}
Each time you make a change to the library app you will have to reinstall it. Then you have to resync the gradle files in your children app. Tools -> Android -> Sync Project With Gradle Files

Categories

Resources