I want to include a module A into Module B.
Module A's build.gradle includes packackingOptions that need to be executed.
These packackingOptions are executed when I build module A. They are not executed when I build module B, which imports module A.
How can I make sure that the packackingOptions from module A's build.gradle are also executed when importing module A into module B?
Module B's build.gradle looks like this:
dependencies {
implementation project(':A')
}
Module A's build.gradle looks like this:
android {
packagingOptions {
pickFirst 'assets/**'
}
}
I set up the project structure as follows:
buildscript-test-app
|
|
buildscript-test-lib
| \------------------------\
| |
buildscript-test-lib-sub-a buildscript-test-lib-sub-b
Both lib-sub-* contain assets/foo.txt with different contents.
build.gradle of buildscript-test-lib:
apply plugin: 'com.android.library'
android {
// omitted default config stuff
packagingOptions {
pickFirst 'assets/**'
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation project(':buildscript-test-lib-sub-a')
implementation project(':buildscript-test-lib-sub-b')
}
build.gradle of buildscript-test-app:
apply plugin: 'com.android.application'
android {
// omitted default config stuff
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation project(':buildscript-test-lib')
}
Gradle always picks the file from buildscript-test-lib-sub-a regardless of the order of dependencies (presumably because of alphabetic ordering).
Something else in your buildscript must be wrong if this doesn't work. If it doesn't work, can you provide more details on the build.gradle of your app module and library modules?
Maybe you are overriding pickFirsts in your app. If that's the case, you should instead of pickFirsts = [somevalue] do pickFirst += 'foo' or pickFirst = 'foo'
Related
I've started a hello world project in Android Studio.
I've added test-shared as a module because the files in there need to be seen by test and androidTest.
settings.gradle:
include ':app'
include ':test-shared'
rootProject.name = "My Application"
build.gradle (app level):
dependencies {
androidTestImplementation(project(":test-shared"))
testImplementation(project(":test-shared"))
}
build.gradle (test-shared):
plugins {
id 'java-library'
}
dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.4.2"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3"
implementation "junit:junit:$junit"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.2'
testImplementation "junit:junit:$junit"
}
And within ExampleInstrumentedTest I try to call a method in MainCoroutineRule:
#RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
#Test
fun useAppContext() {
MainCoroutineRule().doSomething()
}
}
Which gives the error message:
Unresolved reference: test
for the test directory, the same result.
change build.gradle test-shared to:
apply plugin: 'kotlin'
dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.4.2"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3"
implementation "junit:junit:$junit"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.2'
}
and add:
packagingOptions {
exclude "META-INF/licenses/**"
exclude "META-INF/AL2.0"
exclude "META-INF/LGPL2.1"
}
to build.gradle App level
An alternative solution will be to use a specific folder inside the app module, for example sharedTest
then in your build.gradle.kts for app you could have something like this
android {
sourceSets {
this.getByName("androidTest") {
resources.srcDirs("src/androidTest/resources", "src/sharedTest/resources")
}
this.getByName("test") {
resources.srcDirs("src/test/resources", "src/sharedTest/resources")
}
}
}
This ensures that test and androidTest will use the resources in testFolder
Resource for how to set up a shared Test folder.
https://www.youtube.com/watch?v=wEmFifgS0PY
In the app gradle add the following code block, which allows the androidTest and test source set to access resources within the package, without this section the java folder will remain grey and can't be properly accessed.
android {
sourceSets {
androidTest.java.srcDirs += "src/test-shared/java"
test.java.srcDirs += "src/test-shared/java"
}
}
add junit dependency to your build.gradle (app level)
dependencies {
...
testImplementation "junit:junit:$junit"
}
I imported the sample app in Android Studio under the location section. I then proceeded to update most of the dependancies. I then attempted to add Firebase and that's when things went south. The module build.gradle is below.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.2'
}
}
apply plugin: 'com.android.application'
repositories {
jcenter()
}
dependencies {
compile 'com.google.android.gms:play-services-location:10.0.1'
compile 'com.google.android.gms:play-services-maps:10.0.1'
compile 'com.github.bumptech.glide:glide:3.6.1'
compile 'com.google.maps.android:android-maps-utils:0.4.4'
compile 'com.android.support:appcompat-v7:25.0.1'
compile 'com.android.support:recyclerview-v7:25.0.1'
compile 'com.android.support:design:25.0.1'
compile 'com.google.android.gms:play-services-wearable:10.0.1'
compile 'com.android.support:support-v13:25.0.1'
compile project(':Shared')
wearApp project(':Wearable')
}
// The sample build uses multiple directories to
// keep boilerplate and common code separate from
// the main sample code.
List<String> dirs = [
'main', // main sample code; look here for the interesting stuff.
'common', // components that are reused by multiple samples
'template'] // boilerplate code that is generated by the sample template process
android {
compileSdkVersion 25
buildToolsVersion '24.0.2'
defaultConfig {
minSdkVersion 18
targetSdkVersion 25
versionCode 1
versionName "1.0"
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
sourceSets {
main {
dirs.each { dir ->
java.srcDirs "src/${dir}/java"
res.srcDirs "src/${dir}/res"
}
}
androidTest.setRoot('tests')
androidTest.java.srcDirs = ['tests/src']
}
productFlavors {
}
}
apply plugin: 'com.google.gms.google-services'
The root build.gradle is below.
buildscript {
// ...
dependencies {
// ...
classpath 'com.google.gms:google-services:3.0.0'
}
}
And the error I receive is :
Error:Could not find com.google.gms:google-services:3.0.0.
Searched in the following locations:
file:/C:/Android/Android Studio/gradle/m2repository/com/google/gms/google-services/3.0.0/google-services-3.0.0.pom
file:/C:/Android/Android Studio/gradle/m2repository/com/google/gms/google-services/3.0.0/google-services-3.0.0.jar
Required by:
:ToledoZoo:unspecified
Using the latest SDK, and all. Added the google.json file to the app directory as well. I am sure it is something small I am missing, but yet... still missing it!
The module build.gradle is below
app/ is a module, and the buildscript block should not be within that.
The app build.gradle is below.
If by this, you mean build.gradle in the root of the project, then it is that file where you add the classpath of the play services.
Refer. https://firebase.google.com/docs/android/setup#add_the_sdk
Note, when the documentation says
buildscript {
// ...
dependencies {
// ...
classpath 'com.google.gms:google-services:3.0.0'
}
You do not literally copy the // ... pieces. It means "leave what is there already".
If you have a single module Gradle project, then that might make sense looking at your question, and so you need to have
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.2'
classpath 'com.google.gms:google-services:3.0.0'
}
}
apply plugin: 'com.android.application'
// rest of gradle file
I'm not a Gradle expert. That said, the layout of your build.gradle files is unconventional. Typically, in the module file, the dependencies block is after the android block. Examples of build files are in the Firebase sample project. Take a look at this sample project build file and this sample module build file.
I have an Android application module (app) and an Android library module (library). Both app and library contain these same dependencies:
dependencies {
compile 'com.squareup.okhttp:okhttp:2.4.0'
compile 'com.squareup.retrofit:retrofit:1.9.0'
compile 'io.reactivex:rxjava:1.0.13'
compile 'io.reactivex:rxandroid:0.25.0'
}
However when I try to add that block to the project build.gradle, it complains about not knowing the "compile" DSL.
EDIT: I'm asking about putting this dependencies block in the PROJECT build.gradle, to avoid repeating in each module's build.gradle.
As of Gradle Plugin version 3.0.0 there is a nicer way to do this. We can control whether each dependency is available for only the current module, or for the current module AND any modules which depend on it. This will allow us to easily share dependencies across modules within a project.
Here's how we used to declare dependencies:
compile 'example.dependency:1.0.0'
Here are the new configurations which should replace compile:
implementation 'example.dependency:1.0.0' --> this dependency is only used within this module
api 'example.dependency:1.0.0' --> this dependency will also be available in any builds that depend on this module
Here's how to do that with the architecture you mentioned in the question. Assuming that we have a module named 'library' that is consumed by the 'app' module, we can use the api configuration to declare that the dependency should be shared with any module that depends on it.
library module build.gradle
dependencies {
// dependencies marked 'implementation' will only be available to the current module
implementation 'com.squareup.okhttp:okhttp:2.4.0'
// any dependencies marked 'api' will also be available to app module
api 'com.squareup.retrofit:retrofit:1.9.0'
api 'io.reactivex:rxjava:1.0.13'
api 'io.reactivex:rxandroid:0.25.0'
}
app module build.gradle:
dependencies {
// declare dependency on library module
implementation project(':library')
// only need to declare dependencies unique to app
implementation 'example.dependency:1.0.0'
}
Please see this guide for further information and diagrams.
The dependencies block(closure) needs DependencyHandler as delegate
You need to pass DependencyHandler of each project to shared dependencies in project gradle.build.
project build.gradle
ext.sharedGroup = {dependencyHandler->
delegate = dependencyHandler
compile 'com.squareup.okhttp:okhttp:2.4.0'
compile 'com.squareup.retrofit:retrofit:1.9.0'
compile 'io.reactivex:rxjava:1.0.13'
compile 'io.reactivex:rxandroid:0.25.0'
}
app build.gradle
dependencies {
sharedGroup dependencies
}
ref. https://github.com/b1uec0in/DependencyVersionResolver
(see 2. Using default dependency group.
This sample explains many other tips for sharing library version, sdk versions ... for large project that have many modules.)
You can define shared gradle dependencies in the library module, and if the app module has the library as a dependency, you won't need to specify everything twice. Taking this further, you could create a 'common' module that requires the shared gradle dependencies, and have both the app & library module require the common module.
You could do something like this where the project build.gradle will specify the dependencies needed as variable names then in the app build.gradle files you just need to include the variable names. This is very useful when you have many modules and don't want to edit everyone when a version number changes!
project build.gradle
buildscript {
ext {
googlePlayServicesVersion = '7.5.0'
supportLibVersion = '22.2.0'
}
... (the rest of your repositories/dependency info here) ...
}
ext {
minSdkVersion=16
targetSdkVersion=21
buildToolsVersion='22.0.1'
compileSdkVersion=21
//Android Dependencies
supportV4 = 'com.android.support:support-v4:' + supportLibVersion
supportAnnotations = 'com.android.support:support-annotations:' + supportLibVersion
recyclerView = 'com.android.support:recyclerview-v7:' + supportLibVersion
cardView = 'com.android.support:cardview-v7:' + supportLibVersion
palette = 'com.android.support:palette-v7:' + supportLibVersion
appCompat = 'com.android.support:appcompat-v7:' + supportLibVersion
multidex = 'com.android.support:multidex:1.0.1'
appCompat = 'com.android.support:appcompat-v7:' + supportLibVersion
supportDesign = 'com.android.support:design:' + supportLibVersion
playServicesAnalytics = 'com.google.android.gms:play-services-analytics:' + googlePlayServicesVersion
}
app build.gradle file
dependencies {
compile rootProject.ext.supportV4
compile rootProject.ext.appCompat
compile rootProject.ext.supportAnnotations
compile rootProject.ext.recyclerView
compile rootProject.ext.cardView
compile rootProject.ext.palette
compile rootProject.ext.appCompat
compile rootProject.ext.multidex
compile rootProject.ext.supportDesign
compile rootProject.ext.playServicesAnalytics
}
Hope that this helps!
Share libraries using ext block in the root project module
This is an easy way to use the library across all modules in the
android project
Please follow these steps:
Add ext block (it is used to define extra properties for the project) in root project gradle file
Add common libraries in with variable name in ext block
e.g name = [
libraries without implementation keyword
]
Used this ext block in module level using implementation and variable name
e.g implementation variable_name
See below code for complete implementation
build.gradle :project
buildscript {
... (the rest of your repositories here) ...
}
ext { **// ext block start here**
appModuleLibraries = [
commonLibraries,
/*Projects*/
project(':hco-cutout'),
project(':utils')
]
commonLibraries = [
/*Android Libs*/
'androidx.core:core-ktx:1.7.0',
'androidx.appcompat:appcompat:1.4.1',
'com.google.android.material:material:1.5.0',
'androidx.constraintlayout:constraintlayout:2.1.3',
/*Gesture viw for image zooming */
'com.alexvasilkov:gesture-views:2.5.2',
]
cutoutModulleLibraries = [
commonLibraries,
project(':utils'),
// Selfie segmentation
'com.google.mlkit:segmentation-selfie:16.0.0-beta4',
/*checker board drawable*/
'com.github.duanhong169:checkerboarddrawable:1.0.2',
]
} **// ext block end here**
build.gradle :app
dependencies {
/*App Module Libraries in root project gradle*/
implementation appModuleLibraries
}
build.gradle :cutout
dependencies {
/*cutout Module Libraries in root project gradle*/
implementation cutoutModulleLibraries
implementation project(':utils')
}
Hope that this helps!
Based on #SMKS answer, I would prefer this solution for transitive option capability and simplicity
project build.gradle
buildscript {
... (the rest of your repositories/dependency info here) ...
}
ext {
googlePlayServicesVersion = '7.5.0'
supportLibVersion = '22.2.0'
}
app build.gradle file
dependencies {
compile 'com.android.support:support-v4:' + supportLibVersion
compile ' com.android.support:support-annotations:' + supportLibVersion
compile = 'com.android.support:recyclerview-v7:' + supportLibVersion {
transitive = true // do not know if this make sens/interest just for example
}
...
}
I'm new to gradle. Please help me understand how to use the keyword "provided" that is in build.gradle dependencies block.
And what is the difference between this "provided" with "providedCompile" and "providedRuntime"?
build.gradle:
apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'
...
dependencies {
def presentationDependencies = rootProject.ext.presentationDependencies
def presentationTestDependencies = rootProject.ext.presentationTestDependencies
compile project(':domain')
compile project(':data')
apt presentationDependencies.daggerCompiler
compile presentationDependencies.dagger
compile presentationDependencies.butterKnife
compile presentationDependencies.recyclerView
compile presentationDependencies.rxJava
compile presentationDependencies.rxAndroid
provided presentationDependencies.javaxAnnotation //what is this???
...
}
EDIT
The project in question has no mention of
configuration {
provided
}
and it still compiles!
The project is Android-cleanArchitecture
TIA
Gradle has no built in support for the provided dependency scope.
However this blog (credit goes to Danny, the blog's writer) describes how it can be emulated.
In short you need to provide a new configuration named "provided":
configurations {
provided
}
Then add this configuration to the relevant source sets configurations:
sourceSets {
main.compileClasspath += configurations.provided
test.compileClasspath += configurations.provided
test.runtimeClasspath += configurations.provided
}
And finally you're good to go:
dependencies {
provided <your dependency>
}
Note that according to the blog post if you're using Eclipse there's a "major flaw" but the post also provides a workaround for that.
I have a Android app project that depends on a vanilla Java project (':Common'). ':Common' depends on Guava which is located in the Java project's 'lib' directory. The java code in the android project references Guava classes (e.g. the 'Lists' class) as well as classes defined within ':Common'. The compilation of the android project fails due to not being able to find the 'Lists' class but is able to find the classes defined within ':Common' itself. I know this is a configuration that would normally work in a pure Java scenario, but I can't figure out why it fails in this Android case.
NOTE: Adding 'compile fileTree(dir: '../Common/lib', include: ['*.jar'])' to the dependencies of the Android project fixes the compilation error, but obviously this is suboptimal (you shouldn't have to define dependencies in two places like that in gradle).
The build.gradle file for my android project looks like:
apply plugin: 'com.android.application'
android {
compileSdkVersion 20
buildToolsVersion "20.0.0"
defaultConfig {(omitted)}
sourceSets {
main.manifest.srcFile 'AndroidManifest.xml'
main.java.srcDirs = ['src']
main.resources.srcDirs = ['resources']
main.res.srcDirs = ['res']
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile (project(':Common'))
}
The build.gradle file for my java library project (':Common') looks like:
apply plugin: 'java'
sourceSets {
main.java.srcDirs = ['src']
}
dependencies {
compile (fileTree(dir: 'lib', includes: ['*.jar']))
}
A very easy way to solve this problem is to declare guava as a remote dependency of the Common project and have Gradle resolve it at build time. Remote dependencies are transitive and your application would get it by virtue of depending on Common.
Try adding these lines to the build.gradle of the Common project:
dependencies {
compile 'com.google.guava:guava:18.0'
}
Then configure a base repository such as Maven Central:
repositories {
mavenCentral()
}
and remove the guava jar file from the lib/ folder.