I have my main project with some modules: :app, :anotherModule, ... .
Then I forked a library on github and pushed it down in another project. It has two modules, a library :library and a sample app :sample.
What I'm trying to do is to integrate :library in my project at compile time, i.e. without copying files (as someone has suggested here).
What I did
I edited my project settings.gradle and added:
include ':library'
project(':library').projectDir = new File(settingsDir,'../ForkedLibrary/library')
referencing the folder of the forked library. At the same time I added compile project(':library') to my app module.
What's wrong
Compiling fails with:
Could not find property 'ANDROID_BUILD_SDK_VERSION' on project ':library'
I know why it happens: ForkedLibrary/library/build.gradle is referencing some project values in ForkedLibrary/gradle.properties, which is something like:
ANDROID_BUILD_MIN_SDK_VERSION=14
ANDROID_BUILD_TARGET_SDK_VERSION=23
ANDROID_BUILD_SDK_VERSION=23
ANDROID_BUILD_TOOLS_VERSION=23.0.0
... + LOTS of other stuff, POM_ info, version names, ...
I could fix this by copy-pasting these lines into my project gradle.properties, but it makes no sense to have :library-specific stuff in my own gradle properties files. That ForkedLibrary properties files includes things unrelated to my project, like original developer info and other POM_ fields.
So
How to solve this (without including ForkedLibrary properties in my own gradle.properties file)?
It should be a comment, but it is too long. I will delete it if it doesn't help you.
The ForkedLibrary/library/build.gradle as you described in your question is using the ForkedLibrary/gradle.properties.
It works only in the ForkedLibrary specific project because the other project uses its own gradle.properties.
I guess the library/build.gradle file has somenthing like:
project.VERSION_NAME
You can refer the official doc:
The configuration is applied in following order (if an option is configured in multiple locations the last one wins):
from gradle.properties in project build dir.
from gradle.properties in gradle user home.
from system properties, e.g. when -Dsome.property is set on the command line.
In this case you have to copy the properties in your build.properties
There is an alternative that I have never tried in this case, something like this:
processResources {
expand(project.properties)
}
As you can read in the official doc:
Copies resources from their source to their target directory, potentially processing them. Makes sure no stale resources remain in the target directory.
And the expand method is:
Expands property references in each file as it is copied.
Related
I created a new project in Android studio and got many files generated, where as my actual code is found in just one folder - src.
Why the so complicated structure? Please explain the motivation of putting meta-files at the root of the project instead of some inner folder named gradle.
Android build system consists of an Android plugin for Gradle. Gradle
is an advanced build toolkit that manages dependencies and allows you
to define custom build logic. Android Studio uses a Gradle wrapper to
fully integrate the Android plugin for Gradle.
Android Studio projects contain a top-level build file and a build file for each module. The build files are called build.gradle, and they are plain text files that use Groovy syntax to configure the build with the elements provided by the Android plugin for Gradle.
Gradle is an automated build toolkit that allows the way in which projects are built to be configured and managed through a set of build configuration files. This includes defining how a project is to be built, what dependencies need to be fulfilled for the project to build successfully and what the end result (or results) of the build process should be. The strength of Gradle lies in the flexibility that it provides to the developer.
For more info you may visit
Gradle Tutorial
Android Application Modules
First of all if you don't want to see those metadata... you can change it(see Image)..
gradle is required to compile your project. for example: In gradle file we specify minsdk version,maxsdk version and dependencies etc
To Know more about gradle go to http://gradle.org/the-new-gradle-android-build-system/
Why the so complicated structure?
IMHO the structure you are referring to is pretty straightforward but your assumption that all those meta-files are related with gradle is wrong.
Meta-files related with your android application are located inside the "app" sub-folder. You have some gradle files there because those are for the purpose of building that specific module.
As pointed out before in a previous answer the best resource to understand the file tree structure for this part is here.
You also have some metadata generated by the IDE (.idea sub-folder):
IntelliJ IDEA stores the configuration data for projects and their
components in plain text XML files making it easy to manage and share
project configuration data with others.
And .iml files:
A module is a discrete unit of functionality which you can compile,
run, test and debug independently.
Modules contain everything that is required for their specific tasks:
source code, build scripts, unit tests, deployment descriptors, and
documentation. However, modules exist and are functional only in the
context of a project.
Configuration information for a module is stored in a .iml module
file. By default, such a file is located in the module's content root
folder.
More info about can be found here.
Please explain the motivation of putting meta-files at the root of the
project instead of some inner folder named gradle.
As mentioned before in some previous answers some metadata is related with the configuration of your project itself and some is module-specific. One example is the build.gradle files. The global file has this comment:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
About the motivation I only assume it was for simplicity and to keep the semantics of the project structure. Other possibility is that it was just by convention.
Whenever I made a new android studio project, I usually have to add the same handful of libraries to my build.gradle file. To save time, is there a way to modify the template for the generated build.gradle file to include these libraries? I found a way to do that for gradlew and for the parent gradle file but not for the app itself. Any help is appreciated.
Cheers!
I'm creating projects with dependencies in Android Studio. I know how to link projects by adding modules.
But I realized that 'importing modules' create a copy of the libProject inside the project.
Is there a way to prevent that ? Like an 'external module' ?
Since i'm in charge of both project, I want to be able to push changes to the libProject Repo, without having to copy paste files between folders.
Thanks
Yes, you can do it. The module needs to have a Gradle build file set up for it. If it's got that, then in the project you're linking to it, add this to the settings.gradle file at the project root:
include ':libraryName'
project(':libraryName').projectDir=new File('/path/to/library')
where the path you specify in the second line is the path to the directory containing the library's build.gradle file. The path can be relative or absolute.
The solution:
include ':libraryName'
project(':libraryName').projectDir=new File('/path/to/library')
was not working for me. After couple of wasted hours I figured out the issue. There are two build.gradle files, one for project and one for library name. If the library is in the folder '\MyLib' then there will be a build.gradle in '\MyLib' and another at '\MyLib\app'. You have to point to the '\MyLib\app' and not '\Mylib'.
Hopefully this saves some time for others.
If you have, like myself, have multiple modules (I only realised today that copies were included, I thought that the project included links to the source.)
You can have multiple modules/projects along the lines of :-
include ':app', ':sqlwords', ':dbindex', ':dbcolumn', ':dbtable', ':dbdatabase', ':displayhelp', ':pickdate'
project(':sqlwords').projectDir= new File('d:/Android_Applications/Modules/sqlwords')
project(':dbcolumn').projectDir= new File('d:/Android_Applications/Modules/dbcolumn')
project(':dbtable').projectDir= new File('d:/Android_Applications/Modules/dbtable')
project(':dbindex').projectDir= new File('d:/Android_Applications/Modules/dbindex')
project(':dbdatabase').projectDir= new File('d:/Android_Applications/Modules/dbdatabase')
project(':displayhelp').projectDir= new File('d:/Android_Applications/Modules/displayhelp')
project(':pickdate').projectDir= new File('d:/Android_Applications/PickDateShowCase/pickdate')
You can also use android { sourceSets{ main.java.srcDirs += '../../../library/src' }} in your app build.gradle . Not sure about supporting all android resources, for pure java library works well.
Question as in title. A similar question was asked here, and the only workaround that time was to publish the project into a local Maven repository.
Is this problem fixed (as claimed by some) in Android Studio 0.5.+? In its release note there is a statement that says "Support for source folders outside the module content root". Does that mean we can finally import the library from outside the project folder?
I tried File->Import Project.. but it doesn't work.
EDIT 2: See accepted answer for latest solution (as of 0.8.+)
EDIT:
My project directory structure has only one module main which looks like this
MyApp
main
build.gradle
src
build.gradle
settings.gradle
The library project directory has only one module named like lib (they are all auto-generated when creating a new library project)
MyLibrary
lib
build.gradle
src
build.gradle
settings.gradle
The following line is added into MyApp/settings.gradle:
include ':main', '..:MyLibrary'
The following is added into MyApp/main/build.gradle:
dependencies {
compile project(':..:MyLibrary')
}
The result is the following error:
FAILURE: Build failed with an exception.
* What went wrong:
A problem occurred configuring project ':main'.
> Configuration with name 'default' not found.
As a side note, the library project MyLibrary itself can compile without error. The problem seems to be settings.gradle not being able to recognize the library project structure.
(as of version 2.1+):
Below are the steps that I took to share library source outside of the project directory. Instead of plain Java library, my code is compiled as Android module, but that library module is not contained inside the main project. It is fine with me as long as there are no code duplications and I only need to maintain one set of library code for all projects:
File->new Project. Give a name to your library project (here I use LibraryProject). Continue the remaining steps to create a normal project (since this is intended as a library, I chose "add no activity")
By default, Android studio creates the module named as "app" inside the project folder. To prevent names collision with the actual application module, rename the module to something else (Right click "app" module at left panel->Refactor->Rename).
In the build.gradle inside your library module folder, change the top line
apply plugin: 'com.android.application'
to
apply plugin: 'com.android.library'
and then remove the "applicationId" line under "defaultConfig". Also, since this is a library, remove the xlmns:... namespace and <application ..> body from Manifest.xml as well.
That's all for the library part. Now, to create/modify your main application:
If it is a new project, first create new project File->new Project->ApplicationName.
Open settings.gradle (there should only be one such file in every project) and include the following line (note the missing leading semi-colon in library module):
include ':app', '..:LibraryProject:yourLibraryModule'
Then go to File->Project Structure.
Under the tab "Dependencies" click the green "+" button at right. Select "Module dependency". Choose your library module, then click OK.
You should now be able to use the library classes in your application.
ALTERNATIVE METHOD
If, for some reason, there are still problems with the above method, you can try the following (suggested in [here][1]):
Repeat steps 1 to 4 above. By default the main and external (library) project look something like this:
/MainProject
+ build.gradle
+ settings.gradle
+ app/
+ build.gradle
+ src/
/LibraryProject
+ build.gradle
+ settings.gradle
+ app/
+ build.gradle
+ src/
As usual, refactor the modules name (in android studio right-click module->refactor->rename) to something less confusing, such as
/MainProject
+ build.gradle
+ settings.gradle
+ MainModule/
+ build.gradle
+ src/
/LibraryProject
+ build.gradle
+ settings.gradle
+ LibraryModule/
+ build.gradle
+ src/
Modify the settings.gradle in MainProject:
include ':LibraryModule', ':app'
project(':LibraryModule').projectDir = new File(settingsDir, '../LibraryProject/LibraryModule')
Sync the project and you're done.
Note on Proguard
Currently you should not use a proguard on external library projects/modules. Instead, you replace the following (original answer [here][2])
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt'
}
debug {
minifyEnabled false
}
}
with the following (in build.gradle of the library):
buildTypes {
release {
consumerProguardFiles 'proguard-project.txt'
}
}
where proguard-project.txt is the file that contains the proguard rules for your library project.
[1]: https://stackoverflow.com/a/17490233/1919013
[2]: https://stackoverflow.com/a/31031491
Yes, it works now in 0.5.0. There isn't a friendly UI to it (Import Project isn't what you want, as that creates an entirely new project; Import Module is still broken; see https://code.google.com/p/android/issues/detail?id=62122), but you can set up your build files to make it work.
Let's say you have a directory structure that looks like this:
MyApp
appmodule
build.gradle
src
main
java
build.gradle
settings.gradle
MyPlainJavaLibrary
build.gradle
src
java
Note that MyPlainJavaLibrary isn't underneath the MyApp directory in the filesystem.
Set up your settings.gradle file like so:
include ':appmodule', '..:MyPlainJavaLibrary'
and include a dependency to it in build.gradle like this (don't forget the leading colon):
dependencies {
...
compile project(':..:MyPlainJavaLibrary')
}
This works for me. In my Project viewer, I now see MyApp and MyPlainJavaLibrary as two root-level module directories in the view, and I can make java import statements work across module boundaries and such.
Note that in this default setup, this shared module will only have a single build output folder that will be shared among all the projects using it. This may or may not be what you want. If you'd like to have a different output directory for each project using the shared module, you can probably do some magic with the output directory in the sourceSet; if you want help with this, I'd recommend trying it out on your own and posting a question with details on your work if you get stuck.
You can only have one settings.gradle file per project, so this isn't going to take a whole other multimodule Gradle project and bring in all the modules in one fell swoop; you'll need to bring them in individually. However, it should satisfy the use case of using a module in multiple projects.
I wanted to do something similar for my Android Wear project, where you have mobile and wear modules. In Android Studio 1.5.1, you can do File->New->Module and pick Android Library as your module. This will take care of many of the settings described above and put your library inside your existing Android Wear project.
To make full use of Android Studio, I would recommend initially creating a normal android project. Then, within that project, add a Module "android library" type, and (optionally) a "java library" (if you have code you want to use that may be common to Android applications and to server side code).
Using this mechanism, you do not need to manipulate and modify gradle and manifest files.
I also wanted to use the same collection of classes across projects, I found an easier way.
Put the class files you want to use in their own folder outside all of your project folders.
Make a symlink(linux) or shortcut(win) to this folder and copy it to:
~/src/main/java/com/yourco/yourproject/
in each of your project folders.
You now have a package of all your commonly used classes synced on all your projects. You're welcome.
You are able to use module(as a shared source code base)apply plugin: 'com.android.library' in the project.
[Project vs Module]
Question as in title. A similar question was asked here, and the only workaround that time was to publish the project into a local Maven repository.
Is this problem fixed (as claimed by some) in Android Studio 0.5.+? In its release note there is a statement that says "Support for source folders outside the module content root". Does that mean we can finally import the library from outside the project folder?
I tried File->Import Project.. but it doesn't work.
EDIT 2: See accepted answer for latest solution (as of 0.8.+)
EDIT:
My project directory structure has only one module main which looks like this
MyApp
main
build.gradle
src
build.gradle
settings.gradle
The library project directory has only one module named like lib (they are all auto-generated when creating a new library project)
MyLibrary
lib
build.gradle
src
build.gradle
settings.gradle
The following line is added into MyApp/settings.gradle:
include ':main', '..:MyLibrary'
The following is added into MyApp/main/build.gradle:
dependencies {
compile project(':..:MyLibrary')
}
The result is the following error:
FAILURE: Build failed with an exception.
* What went wrong:
A problem occurred configuring project ':main'.
> Configuration with name 'default' not found.
As a side note, the library project MyLibrary itself can compile without error. The problem seems to be settings.gradle not being able to recognize the library project structure.
(as of version 2.1+):
Below are the steps that I took to share library source outside of the project directory. Instead of plain Java library, my code is compiled as Android module, but that library module is not contained inside the main project. It is fine with me as long as there are no code duplications and I only need to maintain one set of library code for all projects:
File->new Project. Give a name to your library project (here I use LibraryProject). Continue the remaining steps to create a normal project (since this is intended as a library, I chose "add no activity")
By default, Android studio creates the module named as "app" inside the project folder. To prevent names collision with the actual application module, rename the module to something else (Right click "app" module at left panel->Refactor->Rename).
In the build.gradle inside your library module folder, change the top line
apply plugin: 'com.android.application'
to
apply plugin: 'com.android.library'
and then remove the "applicationId" line under "defaultConfig". Also, since this is a library, remove the xlmns:... namespace and <application ..> body from Manifest.xml as well.
That's all for the library part. Now, to create/modify your main application:
If it is a new project, first create new project File->new Project->ApplicationName.
Open settings.gradle (there should only be one such file in every project) and include the following line (note the missing leading semi-colon in library module):
include ':app', '..:LibraryProject:yourLibraryModule'
Then go to File->Project Structure.
Under the tab "Dependencies" click the green "+" button at right. Select "Module dependency". Choose your library module, then click OK.
You should now be able to use the library classes in your application.
ALTERNATIVE METHOD
If, for some reason, there are still problems with the above method, you can try the following (suggested in [here][1]):
Repeat steps 1 to 4 above. By default the main and external (library) project look something like this:
/MainProject
+ build.gradle
+ settings.gradle
+ app/
+ build.gradle
+ src/
/LibraryProject
+ build.gradle
+ settings.gradle
+ app/
+ build.gradle
+ src/
As usual, refactor the modules name (in android studio right-click module->refactor->rename) to something less confusing, such as
/MainProject
+ build.gradle
+ settings.gradle
+ MainModule/
+ build.gradle
+ src/
/LibraryProject
+ build.gradle
+ settings.gradle
+ LibraryModule/
+ build.gradle
+ src/
Modify the settings.gradle in MainProject:
include ':LibraryModule', ':app'
project(':LibraryModule').projectDir = new File(settingsDir, '../LibraryProject/LibraryModule')
Sync the project and you're done.
Note on Proguard
Currently you should not use a proguard on external library projects/modules. Instead, you replace the following (original answer [here][2])
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt'
}
debug {
minifyEnabled false
}
}
with the following (in build.gradle of the library):
buildTypes {
release {
consumerProguardFiles 'proguard-project.txt'
}
}
where proguard-project.txt is the file that contains the proguard rules for your library project.
[1]: https://stackoverflow.com/a/17490233/1919013
[2]: https://stackoverflow.com/a/31031491
Yes, it works now in 0.5.0. There isn't a friendly UI to it (Import Project isn't what you want, as that creates an entirely new project; Import Module is still broken; see https://code.google.com/p/android/issues/detail?id=62122), but you can set up your build files to make it work.
Let's say you have a directory structure that looks like this:
MyApp
appmodule
build.gradle
src
main
java
build.gradle
settings.gradle
MyPlainJavaLibrary
build.gradle
src
java
Note that MyPlainJavaLibrary isn't underneath the MyApp directory in the filesystem.
Set up your settings.gradle file like so:
include ':appmodule', '..:MyPlainJavaLibrary'
and include a dependency to it in build.gradle like this (don't forget the leading colon):
dependencies {
...
compile project(':..:MyPlainJavaLibrary')
}
This works for me. In my Project viewer, I now see MyApp and MyPlainJavaLibrary as two root-level module directories in the view, and I can make java import statements work across module boundaries and such.
Note that in this default setup, this shared module will only have a single build output folder that will be shared among all the projects using it. This may or may not be what you want. If you'd like to have a different output directory for each project using the shared module, you can probably do some magic with the output directory in the sourceSet; if you want help with this, I'd recommend trying it out on your own and posting a question with details on your work if you get stuck.
You can only have one settings.gradle file per project, so this isn't going to take a whole other multimodule Gradle project and bring in all the modules in one fell swoop; you'll need to bring them in individually. However, it should satisfy the use case of using a module in multiple projects.
I wanted to do something similar for my Android Wear project, where you have mobile and wear modules. In Android Studio 1.5.1, you can do File->New->Module and pick Android Library as your module. This will take care of many of the settings described above and put your library inside your existing Android Wear project.
To make full use of Android Studio, I would recommend initially creating a normal android project. Then, within that project, add a Module "android library" type, and (optionally) a "java library" (if you have code you want to use that may be common to Android applications and to server side code).
Using this mechanism, you do not need to manipulate and modify gradle and manifest files.
I also wanted to use the same collection of classes across projects, I found an easier way.
Put the class files you want to use in their own folder outside all of your project folders.
Make a symlink(linux) or shortcut(win) to this folder and copy it to:
~/src/main/java/com/yourco/yourproject/
in each of your project folders.
You now have a package of all your commonly used classes synced on all your projects. You're welcome.
You are able to use module(as a shared source code base)apply plugin: 'com.android.library' in the project.
[Project vs Module]