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]
Related
I have an existing android project project one, in which I want to add a feature lets say SpecialToast. Instead of adding it to the project directly, I want to create this feature as an android library so it can be used in other projects project two.
I am a bit confused on the procedure how to create.
I have gone through https://developer.android.com/studio/projects/android-library and I tried to create a library within project one which does create a library.
New -> New module -> Android library
what is the right procedure
Create a brand new android application and in that application create a new Android library.
In Project one create a new android library.
If option 2 is correct, once I create a android library within project one how can I use it in project one
If option 1 is correct, how can I publish that and test easily with project one
Thanks
R
Update
Both options are possible.
You can create the library module in a separate project and build and export it from there (your option 1). You can export your library by using the gradle wrapper task assemble. For example, if your library module is called brdroid, execute this from your project's root folder:
./gradlew brdroid:assembleRelease
This will create the brdroid-release.aar file in the folder {project root}/brdroid/build/outputs/aar.
You can then either copy the aar file to another project or upload it to a package manager. Either manually or for example with the maven publish plugin.
If you upload it to a package manager, you can add your library as a remote dependency just like you do with other libraries by using implementation or api + your package name, artifact id and version number.
For debugging purpose it is easier to use the library module in a project directly (this is your option 2). Meaning, that an app module and library module are in the same project side by side. In this example, if both modules are in the same project, you need to add the brdroid module as a dependency to project one by adding this in the project one build.gradle file:
implementation project(':brdroid')
Note, that you can still export your library as an aar file and publish it like in option 1.
And in this scenario, it's still possible to keep the library module in a separate project and repository and add it to your app's git-repository and project by using git-submodules. This is a little bit more.
Using git submodules
An example usage of git-submodules can look like this: Let's consider we have this two projects which are in separate git repositories:
My Library which has only the brdroid android library module
MyApplication which has only the app android application module:
In order to add the MyLibrary repository as a git-submodule to the MyApplication git repository, execute this from the MyApplication root folder:
git submodule add -b master https://{url-to-My-Library-git-repository}
The -b master only tells which branch to track. You can change it.
This clones My Library into a new subfolder which is not tracked by the MyApplication repository. It also creates two changes which you need to commit in order to make them permanent.
Next, open settings.gradle from the MyApplication root folder and add the brdroid module to the MyApplication project by changing the first row from:
include ':app'
to
include ':app', 'MyLibrary:brdroid'
MyLibrary is just the folder in which the brdroid module resides.
Also, add brdroid as a dependency to the app module by adding this to the build.gradle file of the app module:
implementation project(':MyLibrary:brdroid')
Your result should now look like this:
Now, app and brdroid are in the same project but the development of brdroid happens in a separate git repository.
I want import .arr in my library module not main module,how can i do?
in my library module build.gradle set aar, err: can not find it.
dependencies {
compile(name:'nameArrFile', ext:'aar')
}
repositories{
flatDir{
dirs 'libs'
}
}
To Add to the answer: From the Android Studio File Menu,
Click Import .JAR/.AAR Package then click Next.
Enter the location of the compiled AAR or JAR file then click Finish.
Import the library module to your project
(the library source becomes part of your project):
Click File > New > Import Module.
Enter the location of the library module directory then click Finish.
The library module is copied to your project, so you can actually edit the library code. If you want to maintain a single version of the library code, then this is probably not what you want and you should instead add the compiled AAR file as described above.
Make sure the library is listed at the top of your settings.gradle file, as shown here for a library named "my-library-module":
include ':app', ':my-library-module'
Open the app module's build.gradle file and add a new line to the dependencies block as shown in the following snippet:
dependencies {
compile project(":my-library-module")
}
Click Sync Project with Gradle Files.
In this example above, the compile configuration adds the library named my-library-module as a build dependency for the entire app module.
If you instead want the library only for a specific build variant, then instead of compile, use buildVariantNameCompile. For example, if you want to include the library only in your "pro" product flavor, it looks like this:
Your code is correct. Make sure the following things are in place and it will work just fine.:
nameAarFile should be just the file name without the extension .aar. Also make sure there is no spelling error in the file name.
make sure the extension of the actual aar file is right. I see you have mistyped it as arr at several places in your question (I corrected). make sure the same is no the case with extension in your file name
Make sure the .aar file is in the libs folder. If in any other directory either move to libs or include the other directory under FlatDir - > dirs
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.
As Gradle does not support apklib dependencies how can one migrate from apklib dependencies to aar dependencies? Is it possible to either manually or automatically convert apklib dependency to aar? If yes - how, if no - why not?
In this question I assume that I don't have original project for apklib, but rather the file itself.
apklib doesn't contain object files, only source files, so the only way it can be included in any project is by recompiling it. According to some docs you can read at:
Android dependencies : apklib vs aar files and https://plus.google.com/+ChristopherBroadfoot/posts/7uyipf8DTau
The apklib format was invented as a way to share Android code+resources. It’s essentially a zipped up Android library project, which was already the status quo for code+resource sharing.
And you can see in Chris Broadfoot's post that the task that generates the apklib just zips up the AndroidManifest.xml file and the src and res directories:
task apklib(type: Zip) {
appendix = extension = 'apklib'
from 'AndroidManifest.xml'
into('res') {
from 'res'
}
into('src') {
from 'src'
}
}
Note that his post is about creating an apklib from Gradle, which is a slightly weird thing to want to do, but it provides a pretty clear idea of how one of these things is structured.
The good news is that this is "standard" Android project structure as of when Eclipse was the primary IDE, and Android Studio knows how to import modules that look like this. So follow these steps:
Unpack your apklib into a temporary directory. It's in zip format, so something like unzip library.apklib should work.
Look at what's unpacked. You should see a directory containing AndroidManifest.xml, src, and res folders.
In Android Studio, inside an existing project, choose File > Import Module and point it at the directory from step 2.
Android Studio should manage the import by copying the files into your project in a new module, arranging them in its preferred directory structure, and will add a build.gradle file for the module.
At this point you're up and running. If you actually want the .aar file, then check to see if your new module is set up as a library module or an application module. In its build.gradle, if you've got apply plugin: 'com.android.library' then it's a library module, and Gradle will generate an .aar as part of the build: it will be in the build/outputs/aar directory after a successful build.
If your module imported as an app module and not a library (apply plugin: 'com.android.application', then change that apply plugin statement, and you may also need to remove the applicationId statement from the build file. Now it should compile as a library and generate a .aar.
Happy coding!
You cannot convert the apklib to aar. You have to update the dependencies manually to point to an aar file. The aar is compiled and contain lint and proguard rules which the apklib can't necessarily determine automatically.
You can read a bit more on the differences here:
Android dependencies : apklib vs aar files
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]