We are trying to develop 2 gradle flavors to speed up our development process:
the local flavor that compiles our libraries as modules
the remote flavor that uses the latest SNAPSHOTS of our libraries
I have declared two flavors in gradle:
productFlavors {
local {}
remote {}
}
For now, let's assume that both our local and remote libraries are available as local modules (for debugging purpose). I have created a sample project here. Since each library has sub libraries that are also supposed to be local or remote, I have added:
dependencies {
localCompile project(path: ':mylibrary', configuration: "localDebug")
remoteCompile project(path: ':mylibrary2', configuration: "remoteRelease")
}
Now it becomes tricky. If I call gradle assembleLocalDebug, I get this line:
:mylibrary2:compileRemoteReleaseJavaWithJavac UP-TO-DATE
In the case of the sample app, it compiles. But in our case, we have a project where the newest features cannot be found in the SNAPSHOTS (since they are not published yet). This shouldn't happen since we are building in local. Is there any way to prevent gradle from compiling the remote flavor?
What you want to do might be solved in the latest versions of Gradle.
With Gradle 3.1, you can now use the so-called "composite builds".
As an example, say you have a library L, deployed on a remote repository, and a project P depending on L. Imagining that both L (say, "libL/") and P ("projectP") are in the same directory on your system, you can build the "local" version by running the following command from projectP:
$ ./gradlew --include-build ../libL build
Moreover, composite builds are coming in Android Studio!
Related
Trying to find the bare minimum source and build files needed to build an android project in Android Studio. I want to publish to github and avoid uploading generated build files or binaries.
I do have a Android.gitignore from but I still see some more files getting pushed into the repo which may not be necessary. I understand the few obvious ones but about others, do I need them and if so kindly explain the usage.
So the question, do I need the following and if so then a short description of why?
root
build.gradle
gradle.properties
gradlew
gradlew.bat
settings.gradle
/app
app/build.gradle
app/proguard-rules.pro
/gradle (tested, android can re-download/generate following it if not present)
gradle/wrapper/gradle-wrapper.jar
gradle/wrapper/gradle-wrapper.properties
This question can have two different answers based on the meaning of the word needed.
First (the real one)
Assuming your project has currently those files, if your question is:
Should I commit these files on my Git repo?
The answer is yes, all of them, and I'm explaining why:
root
build.gradle -> defines the configuration for all the Gradle modules in your project (e.g. use the same remote repositories to download some Gradle plugins)
gradle.properties -> defines some optional flags used when building the app (e.g. enabling the incremental KAPT, enabling the AndroidX jetifier)
gradlew -> invokes the Gradle wrapper (which can be found under gradle/wrapper/gradle-wrapper.jar) to avoid to have Gradle installed when building your project on Darwin/Linux
gradlew.bat -> the same of gradlew but for Windows
settings.gradle -> defines the list of modules which are part of your project
app/
app/build.gradle -> defines the configuration only for your app module (e.g. its build types, its flavors, its version code and version name)
app/proguard-rules.pro -> defines the obfuscation rules when your app enables the minification
gradle/
gradle/wrapper/gradle-wrapper.jar -> provides the same version of the Gradle wrapper jar for all the users. This is very important because it forces the users to use the same version of the Gradle wrapper to compile your app
gradle/wrapper/gradle-wrapper.properties -> same as above, it defines which version of the Gradle wrapper you need
Second (the useless one)
Now, I'll give you the answer to the question:
Are these files strictly needed to compile an Android project?
To successfully compile an Android project with Gradle you just need the root build.gradle if you have Gradle installed on your machine or build.gradle + the wrapper files if you have not Gradle installed on your machine.
Theoretically you can:
put your application code in the root project and that avoids you one build.gradle and settings.gradle
disable the obfuscation and that avoids you proguard-rules.pro
remove gradle.properties and set the properties via command line
Obviously this solution won't happen on a real project scenario.
After migrating to Android plugin for Gradle 3.0 the OSS license plugin (https://developers.google.com/android/guides/opensource) no longer includes the licenses from the project's library modules dependencies. Only the "app" module.
I'm using com.google.gms:oss-licenses:0.9.1 and com.google.android.gms:play-services-oss-licenses:11.8.0
If I 'apply' the plugin to all my modules, the third_party_license data is generated in the raw folder for each module. But in the end only the data from the app module end up in the APK.
Is there any workaround for this problem?
Yes that is correct.
Based on my search on how the plugin works, the plugin would generate the data into the res/raw folder of the artifact (aar or apk, but not jar files) based on POM files it can get from the libraries. Then the rest of merging is done by Gradle Android Plugin, and not by the OSS License Plugin, which merges the res folders from all of the sources (dependency libs, modules, main app etc.). However here's is the issue, upon merging, the Android Gradle Plugin would choose one if there are duplicates of the same resource (link to explanation), and the one that is chosen is based on a priority, meaning since both the app module and the lib module are generating the R.raw.third_party_license resource which are duplicates, the one from the app module has a higher priority of being included than the one from the module hence the license information from the module are not included.
There are several ways of fixing this:
Include the same dependencies from your library module in your app module. This is probably the worst idea to do but it does not affect your app since Gradle would automatically resolve the dependencies without any issues especially if they will be of the same version, if they were of different versions then Gradle would choose the latest.
Rather than using a module dependency, publish the module to a maven repo (locally or remotely, here's a link to show how it could be done locally), and add it's dependency as such: implementation 'com.mygroup:library:1.0'. Don't forget to remove it from the project build.settings file. This would generate the POM file of the library module and hence get the plugin to read it and include it's library licenses. This means that the library should be compiled and published before compiling the app module, but also it could lead to some weird compiling issues and confusions when errors happen.
Unfortunately there is one more way that I thought would work however it didn't. It is by changing the dependencies in your library module to api instead of implementation. This would expose the library dependencies into the app module dependencies but would increase the build time of the project. But finally it didn't generate the raw resources properly because it seems that the OSS License Plugin only reads the dependencies from a POM file of library and in this case the POM file is not being generated even if the library module dependencies were exposed. Probably should post this as an enhancement or bug request to the developers of the plugin.
I have small log library and it is published to jcenter. I need to have two versions of the library - debug and release. To do this I found flag publishNonDefault true and pushed new version of library.
Structure of files in repository before flag was set:
Structure of files in repository after flag was set:
And now
dependencies {
compile 'me.shikhov:wlog:1.3.1'
}
gives me error
Error:A problem occurred configuring project ':Project'.
Could not find wlog.jar (me.shikhov:wlog:1.3.1).
Searched in the following locations:
https://jcenter.bintray.com/me/shikhov/wlog/1.3.1/wlog-1.3.1.jar
I have found syntax for local dependency, for example:
debugCompile project(path: ':myLocalLibrary', configuration: 'debug')
releaseCompile project(path: ':myLocalLibrary', configuration: 'debug')
How to set remote library dependency?
The extra string after the version in the artifact name is the classifier.
The classifier allows to distinguish artifacts that were built from
the same POM but differ in their content. It is some optional and
arbitrary string that - if present - is appended to the artifact name
just after the version number. As a motivation for this element,
consider for example a project that offers an artifact targeting JRE
1.5 but at the same time also an artifact that still supports JRE 1.4. The first artifact could be equipped with the classifier jdk15 and the
second one with jdk14 such that clients can choose which one to use.
Another common use case for classifiers is the need to attach
secondary artifacts to the project's main artifact. If you browse the
Maven central repository, you will notice that the classifiers sources
and javadoc are used to deploy the project source code and API docs
along with the packaged class files.
From here.
Gradle dependency declaration takes the form:
[organisation]:[module]:[revision]:[classifier]#[ext]
so you should be consuming the dependency as:
compile 'me.shikhov:wlog:1.3.1:release#aar'
In my Android projects build.gradle file I have:
dependencies {
compile 'org.apache.directory.studio:org.apache.commons.io:2.4'
compile 'org.apache.commons:commons-collections4:4.0'
}
When I run aapt dump badging I see:
native-code: 'commons-io-2.4.jar'
Clearly commons-io is not native code but the Android Gradle plugin thinks it is. How can I tell the Android Gradle plugin this library does not contain native code? Also curious how did it decide what architecture this library is? It seems to have picked some variety of arm since the APK won't install on a intel-based Android emulator, it gives the error: INSTALL_FAILED_CPU_ABI_INCOMPATIBLE.
You may be using the incorrect Commons IO library. Try:
http://mvnrepository.com/artifact/commons-io/commons-io/2.4
The version you're using seems to be specific to Apache Directory Studio 2.4 which seems to be a desktop app.
I once had troubles introducing a dependency on commons-io:2.4 into my build code. The problem is that Gradle itself comes with a version of commons-io. In my case it could be fixed with this:
sourceSets {
main {
compileClasspath = configurations.compile.minus files("$gradle.gradleHomeDir/lib/commons-io-1.4.jar")
}
}
I took this snippet from My Gradle project depends on commons-io 2.4, but Gradle puts $GRADLE_HOME/commons-io-1.4.jar into the classpath, causing failures
But be aware that it is not recommended to use different versions of libraries to come with Gradle.
You can find more information about this here: https://discuss.gradle.org/t/unable-to-use-commons-io-2-4-because-gradle-forces-the-loading-of-commons-io-1-4/8021
This might aswell be completely unrelated :)
When I run the installClientLibs from Android Studio (with gradle command as well) for an Endpoint, the jar is generated with this name:
libEndpoint-v1-1.18.0-rc-SNAPSHOT
But since some days ago, it's being generated as:
libEndpoint-v1-1.19.0-SNAPSHOT
Where do the "18.0-rc" and the "19.0" come from? Why did it change? Is it due to a SDK update maybe?
This is the version of the Google libraries:
google-api-client-1.18.0-rc
google-api-client-android-1.18.0-rc
google-http-client-1.18.0-rc
google-http-client-android-1.18.0-rc
google-oauth-client-1.18.0-rc
These libraries are used to generate android client library for your Android module.
You can see them if you expand External Libraries section in Android Studio.
You can also check what is the latest version in Maven Repository. Just go to http://search.maven.org/ and type one of them. You will notice that 1.19.0 is the newest one as you posted.
If you would like avoid update Android module gradle file every time version changes, you can set your dependency like this:
compile project(path: ':backend', configuration: 'android-endpoints')
where backend is the name of the module. By the way, this is how Google Cloud Endpoint template generates configuration for a while. If you find any difficulties applying this way, try creating new project and generate backend module.