Exclude specific sub-modules from product build - android

Okay, so I have different product flavors and I have different submodules. Right to implement submodule, I do this:
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation project(path: ':A-Android')
implementation project(path: ':B-Android')
implementation project(path: ':C-Android')
}
Is it possible to implement, for instance, submodule :A-Android only for specific product flavor? How?

Yes, can configure dependencies only for specific flavor. Here an excerpt from Declare dependencies documentation :
Declare dependencies
You can configure a dependency for a specific build variant or
testing source set by prefixing the name of the build variant or
testing source set before the Implementation keyword, as shown in the
following example.
dependencies {
// Adds the local "mylibrary" module as a dependency to the "free" flavor.
freeImplementation project(":mylibrary")
// Adds a remote binary dependency only for local tests.
testImplementation 'junit:junit:4.12'
// Adds a remote binary dependency only for the instrumented test APK.
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
For more information, see Add build dependencies.
So, if you have two flavors something like production and development flavor, then you can add the dependencies like this:
dependencies {
productionImplementation project(path: ':A-Android')
DevelopmentImplementation project(path: ':B-Android')
..
}

Related

How to fix 'java.lang.NoClassDefFoundError' in Android .aar project

I have an android .aar library built and I am trying to integrate it with one of the projects. When the app tries to open the initial screen of the .aar library where I have API call using retrofit. I am getting the below exception
java.lang.NoClassDefFoundError: Failed resolution
of:Lokhttp3/OkHttpClient$Builder;
I have not obfuscated or enabled pro-guard in my .aar project.
Below are my .aar Gradle dependencies
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:design:28.0.0'
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.squareup.okhttp3:okhttp:3.12.0'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.squareup.retrofit2:converter-gson:2.2.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
OK, this is a common issue. There are several ways to use an android library(aar) in other projects. For example:
By importing this aar as a module into your sample project by using
implementation project(':mylibrary').
By uploading your aar to a maven repository(artifactory, maven local, Jitpack, etc)
Pay attention to this:
If you are using number 1 above, so you will also have to
add(retrofit, okhttp3, etc) to your sample project with the same
version, because the aar by default doesn't include child
dependencies. That's why you are getting that exception
"java.lang.NoClassDefFoundError: Failed resolution of:
Lokhttp3/OkHttpClient$Builder'".
If you are using number 2 above, so you will have to make sure that your pom.xml file includes your child dependencies, because the server needs to download and have them available in your sample project.
What do I recommend?
I recommend developers to use MavenLocal(), it replicates a real scenario before publishing your aar to a public repository like Jitpack or whatever you want.
How can I do it?
Inside build.gradle of your library module:
apply plugin: 'maven-publish'
project.afterEvaluate {
publishing {
publications {
library(MavenPublication) {
setGroupId 'YOUR_GROUP_ID'
//You can either define these here or get them from project conf elsewhere
setArtifactId 'YOUR_ARTIFACT_ID'
version android.defaultConfig.versionName
artifact bundleReleaseAar //aar artifact you want to publish
pom.withXml {
def dependenciesNode = asNode().appendNode('dependencies')
configurations.implementation.allDependencies.each {
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', it.group)
dependencyNode.appendNode('artifactId', it.name)
dependencyNode.appendNode('version', it.version)
}
}
}
}
}
}
Run assemble and publishToMavenLocal gradle tasks. And you'll see something like this:
In your Sample Project
allprojects {
repositories {
mavenLocal()
...
}
}
implementation '${YOUR_GROUP_ID}:${YOUR_ARTIFACT_ID}:${YOUR_VERSION}'
Let's assume you've built your .aar, and published it to a maven repository (artifactory, nexus, what have you) - e.g., "implementation 'com.mycompany:library:1.0#aar'". Any child dependencies need to be included in the pom.xml delivered by the server to have them available in your application.
Since you've used the "implementation" keyword, those dependencies are considered private to the .aar, and will not be listed in the pom.xml. So they will not be available in your aar, and not automatically imported into the project by gradle.
If you change to the api keyword to "api" instead of implementation, those dependencies become public, and should be listed in the generated pom.xml, and thus should be automatically imported into the project.
This is actually also true also with aar's inside modules, rather than referenced via external systems (e.g. implementation project(':mylibrary') ). If you need the dependencies of mylibrary to run the project, they need to be api.
For reference, you may want to take a look at the Android Studio Dependency Configurations Documentation.
If, however, you're manually including the arr via a files statement (e.g., implementation files('libs/my.aar')), then you don't get automatic dependency management, and you're going to have to add the libraries needed by your aar to the main project manually as well via copy and paste between the build.gradle files.
You can try using fat-aar to solve this https://github.com/kezong/fat-aar-android

Android Gradle 3.0.0 - add library dependency for specific flavors

My app includes a library and a 3 flavor debug, release and custom.
I don't want my app to include the library in 'custom' flavor
Prior to gradle 3.0 I used :
releaseCompile project(path: ':myLib', configuration: "release")
debugCompile project(path: ':..:myLib', configuration: "debug")
// 'custom' ignored
according to google migrate to android plugin for 3.0 I need to use implementation keyword with matchingFallbacks for 'custom' flavor.
I don't want to use 'matchingFallbacks' because I don't want my app to include the lib in 'custom' flavor.
Any idea how can I compile the lib only in debug and release?
edit
maybe its possible to add 'if' statement i.e:
if(flavor != custom){
implementation project 'myLib'
}
I think you can achieve it by using something like this:
dependencies {
// use only mylib for debug and release
releaseImplementation project(path: ':mylib')
debugImplementation project(path: ':mylib')
// this will be used by all the flavor
implementation "com.android.support:appcompat-v7:27.0.2'
}

Javapoet not found in processor

I created an Android library that uses JavaPoet to generate classes. It works well on my local workspace ; even if I include the library module into another project.
Now I'm trying to put my project online through bintray. The project is uploaded correctly, but then when I include it in a new project and build the projet I get this message :
Error:Bad service configuration file, or exception thrown while
constructing Processor object: javax.annotation.processing.Processor:
Provider me.aflak.filter_processor.FilterProcessor could not be
instantiated: java.lang.NoClassDefFoundError:
com/squareup/javapoet/TypeName
I guess it comes from the way I manage the dependencies... Compiletime, Runtime stuff...
This is processor build.gradle :
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation project(':filter-annotation')
api 'com.squareup:javapoet:1.9.0'
compile 'com.google.code.gson:gson:2.8.1'
compile 'com.google.auto.service:auto-service:1.0-rc3'
}
This is annotation buid.gradle :
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.google.code.gson:gson:2.8.1'
}
This is how I include the library in an empty project :
// build.gradle project
repositories {
maven{
url 'https://dl.bintray.com/omaflak/maven'
}
}
// build.gradle module
dependencies {
compile 'me.aflak.libraries:filter-annotation:1.0'
annotationProcessor 'me.aflak.libraries:filter-processor:1.0'
}
Could someone point me out to the right direction ? Thanks !
I finally got the solution (a bit randomly though :p).
I had to add mavenLocal() in the library module.

Gradle group module dependencies based on flavors

The problem that I have is that the regular
dependencies {
compile project(path: ':moduleOne', configuration: "typeRelease")
}
is not enough for my app's purposes. I have quite a list of dependencies with different configurations (and flavors + build types) involved, and what I want to do now is to add some kind of a method to leverage those dependencies.
For example,
dependencies {
flavorOneAnalyticsCompile project(path: ':moduleOne', configuration: "typeRelease")
flavorOneFlurryCompile project(path: ':moduleOne', configuration: "typeRelease")
flavorOneCrashlyticsCompile project(path: ':moduleOne', configuration: "typeRelease")
flavorTwoAnalyticsCompile project(path: ':moduleOne', configuration: "typeStaging")
flavorTwoLoggingCompile project(path: ':moduleOne', configuration: "typeStaging")
}
Is it possible to say "I want all my build variants with FlavorOne to compile moduleOne with typeRelease configuration, and all build varians with FlavorTwo to compile moduleOne with typeStaging configuration"?
Does anybody know how to do it? Is this even possible? I have found here how to use flavor + build type dependencies, but it's quite ugly to have this big fat list of similarly-looking dependencies.
Thanks! :)

How to depend on specific class or package in another Gradle module?

I have two gradle modules, :app and :backend. The backend contains some classes that I need in :app. So normally I would add compile project(':backend') to my app module's dependencies.
However, this adds all of backend and its dependencies to :app. Is there any way to tell gradle to add only specific classes or packages (and their dependencies) from :backend to :app?
EDIT: :backend is a AppEngine module, which contains a whole host of duplicate google dependencies that clash with my android app when I don't use the android-endpoints configuration.
For removing all the transitive dependencies you can
compile (project(path: ':backend', configuration: 'android-endpoints')) {
transitive = false
}
For ignoring some of them
compile (project(path: ':backend', configuration: 'android-endpoints')) {
exclude(group: 'some.group', module: 'some.module')
}

Categories

Resources