My Android app is based on Gradle and it just takes ages to build every time. This is due to the number of modules I have. Even if there are no changes in submodules, it keeps rebuilding every sources.
I was wondering if there is any way to convert these modules to local snapshot dependencies as I'm not updating them often?
I'm pretty sure it's possible but I have a very basic experience with gradle and maven so I can't figure out a simple way to do that.
Basically right now I'm listing my dependencies like that:
dependencies {
compile project(':Library:lib1')
compile project(':Library:lib2')
compile project(':Library:lib3')
}
and I'd like to use something like that:
repositories {
local()
}
dependencies {
compile 'com.lib1:lib:SNAPSHOT-1.0')
compile 'com.lib2:lib:SNAPSHOT-1.0')
compile 'com.lib3:lib:SNAPSHOT-1.0')
}
To use local snapshots use the maven-publish plugin. If you use SNAPSHOT in the version (e.g. 0.0.1-SNAPSHOT) you will publish snapshots to your local repository. For the build.gradle for lib1 you should do something like this:
apply plugin: 'java'
apply plugin: 'maven-publish'
project.version=0.0.1-SNAPSHOT
publishing {
publications {
maven(MavenPublication) {
from components.java
}
}
}
and run the :publishMavenPublicationToMavenLocal target.
In you gradle build file for projects using the library use:
repositories {
local()
}
dependencies {
compile group: 'com.lib1', name: 'lib', version: 'SNAPSHOT-0.0.1', changing: true
}
The 'changing' attribute indicates that not a cached version is used (normally updated once every 24hrs) but always checks for the latest.
Related
Sporadically, my Gradle syncs will fail. I'll be given the unhelpful message that "a 3rd party Gradle plugin" may be the cause. If I open up the Event Log, I'll see the message:
Outdated Kotlin Runtime
Your version of Kotlin runtime in 'Gradle: org.jetbrains.kotlin:kotlin-stdlib:1.2.10#jar' library is 1.2.10-release-109 (1.2.10), while plugin version is 1.2.51-release-Studio3.1-1.
Runtime library should be updated to avoid compatibility problems.
The mismatched number is neither the Kotlin version in my Gradle files, or the version of my Kotlin plugin in Android Studio.
After running a Gradle dependency tree, I found the culprit:
+--- io.realm:realm-android-kotlin-extensions:5.1.0
| \--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.10 -> 1.2.51
I'm not including any realm-android-kotlin-extensions library. I'm assuming that it's added by classpath "io.realm:realm-gradle-plugin:5.1.0" and apply plugin: "realm-android"
This makes matters difficult. If it were a regular dependency, I could try something like
implementation "io.realm:realm-android-kotlin-extensions:5.1.0" {
transitive = false
}
or
implementation "io.realm:realm-android-kotlin-extensions:5.1.0" {
exclude group: "org.jetbrains.kotlin", module: "kotlin-stdlib-jdk7"
}
Theoretically that would probably work. It would be forced to use the newer version of Kotlin, the error would go away, and hopefully Gradle syncs would work and all would be well with the world. But if I try this approach my Gradle sync fails and I get this error in the Event Log:
Gradle sync failed: Could not find method io.realm:realm-android-kotlin-extensions:5.1.0() for arguments [build_2krw7i3nwfkd5lrq1ly9b8huw$_run_closure3$_closure29#7b5b2081] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.
I'm assuming that's because this isn't a dependency I added (perhaps not a public dependency?), that it fails because the dependency is added via the plugin instead of directly in my Gradle file.
So how do I fix this? Perhaps there's a line I can add to tell the Realm plugin to exclude the obsolete dependency? Or am I completely barking up the wrong tree and the solution for my Kotlin version clash issue is something else entirely?
(BTW, if you're wondering why I'm using Realm 5.1.0, 5.3.1 causes some weird bugs in our app, so we're waiting for a later version to be released in the hope that will no longer cause the issues.)
One of the things on my personal "I wish I had known this a year ago" list is that you can manually add what Realm adds to your project instead of relying on the Gradle plugin.
buildscript {
ext.kotlin_version = '1.2.51'
ext.realm_version = '5.3.1'
repositories {
jcenter()
mavenCentral()
}
dependencies {
classpath "io.realm:realm-transformer:5.1.0"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
import io.realm.transformer.RealmTransformer
android.registerTransform(new RealmTransformer(project))
dependencies {
implementation "io.realm:realm-annotations:$realm_version"
implementation "io.realm:realm-android-library:$realm_version"
implementation "io.realm:realm-android-kotlin-extensions:$realm_version" {
exclude group: "org.jetbrains.kotlin", module: "kotlin-stdlib-jdk7"
}
kapt "io.realm:realm-annotations-processor:$realm_version"
}
As per docs.
I try to evaluate the performance of the Realm database for a specific project.
Everything works fine at the moment. I just miss one method. I need a function to get the needed space for storing my realm database.
In case of some other databases I can take the size of the files where it is stored in. How can I get the needed space for my specific realm database?
And more important for me is the version. Evertything I tried works just fine with version 0.88.0
I just need to add the following dependency to my modules gradle file.
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
provided 'io.realm:realm-android:0.80.0'
...
}
If I change this to
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
provided 'io.realm:realm-android:2.2.0'
...
}
I got the following error:
Error:(24, 13) Failed to resolve: io.realm:realm-android:2.2.0-snapshot
How can I change to the newest version?
Because of debugging I got version 2.1.0 working for me. Hope that I can copy the classes of the TestProject to my bigger Evaluation Project without getting errors. If not I will report that.
But first, I need some code to get the needed diskspace for storing the whole database. I need this to compare it to other Databases.
To use Realm's SNAPSHOT version, you need to add their snapshot repository in your build gradle.
buildscript {
repositories {
jcenter()
maven {
url 'http://oss.jfrog.org/artifactory/oss-snapshot-local'
}
}
dependencies {
classpath "io.realm:realm-gradle-plugin:<version>-SNAPSHOT"
}
}
repositories {
jcenter()
maven {
url 'http://oss.jfrog.org/artifactory/oss-snapshot-local'
}
}
To use Realm in your project, you need to apply it as a Gradle plugin (since 0.88.0).
apply plugin: 'realm-android'
For more info, refer to the official documentation: https://realm.io/docs/java/latest/#installation
Remove the -SNAPSHOT part from the version and its actually 2.1.1 is the latest version as for now, so the main part should be
buildscript {
repositories {
jcenter()
}
dependencies {
classpath "io.realm:realm-gradle-plugin:2.1.1"
}
}
They really have some issue with the realm-annotations-processor of version 2.2.0-SNAPSHOT (its missing, check here). The latest version they did provide is 2.0.2-SNAPSHOT and thus if you want to use the SNAPSHOT then you should use 2.0.2-SNAPSHOT version.
I just enabled instant run in my android studio project. (Followed the instructions here)
My project contains git submodules and somehow these do not compile anymore.
This is the error i get:
Error:(8, 0) Cannot change dependencies of configuration
':libraries:my_library:classpath' after it has been resolved.
Any idea what could be wrong there ?
Top level build.gradle:
buildscript {
repositories {
mavenCentral()
jcenter()
maven { url 'https://maven.fabric.io/public' }
}
dependencies {
classpath 'com.android.tools.build:gradle:2.0.0-alpha1'
classpath 'com.novoda:bintray-release:0.2.7'
classpath 'io.fabric.tools:gradle:1.+'
}}
Module build.gradle:
apply plugin: 'android'
apply plugin: 'io.fabric'
android {
defaultConfig {
versionCode 4850
versionName '4850'
compileSdkVersion 23
buildToolsVersion '23.0.1'
}
packagingOptions {
exclude 'META-INF/LICENSE'
exclude 'META-INF/MANIFEST.MF'
exclude 'META-INF/NOTICE'
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
useLibrary 'org.apache.http.legacy'
}
repositories {
mavenCentral()
jcenter()
}
dependencies {
[skip]
compile project(':libraries:my_library:sdk')
}
Library build.gradle
apply plugin: 'com.android.library'
android {
compileSdkVersion 23
buildToolsVersion '23.0.2'
defaultConfig {
minSdkVersion 14
targetSdkVersion 23
}
lintOptions {
abortOnError false
}
}
repositories {
mavenCentral()
}
dependencies {
compile fileTree(include: '*.jar', dir: 'libs')
compile 'com.android.support:support-v4:23.1.0'
compile 'com.android.support:appcompat-v7:23.1.0'
testCompile 'junit:junit:4.12'
}
gradle reads and executes all build.gradle files in all folders of the included modules. As the error shows, it also tries to execute the root build script of :libraries:my_library.
You have to change your settings.gradle and include the library project by setting its 'projectDir':
include ':app'
// Give your library project any module name, i.e. ':sdk'
include ':sdk'
// Then set the project path of the library module
project(':sdk').projectDir = new File('libraries/my_library/sdk')
With this settings.gradle you can reference the library project as gradle dependency with:
compile project(':sdk')
I had the same problem. I resolved it by removing the classpath in the submodule Top-level build.gradle file.
dependencies {
// classpath 'com.android.tools.build:gradle:1.0.0'
}
I'm not sure if it's the best thing to do, but it worked for me.
I had the same problem. I compared it to the (working) sample project by #RaGe and found the minor difference.
The sub project folder has to start with a Upper case letter.
Here is the change I did on #RaGes sample to break it and get it working again.
Broken structure:
android-multi-project-sample
+ .gralde
+ .idea
+ app
+ build
+ gradle
+ myApplication2
- .gitignore
- android-multi-project-sample.iml
- build.gradle
- gradle.properties
- gradlew
- gradlew.bat
- local.properties
- settings.gradle
results in the following error:
Error:(8, 0) Cannot change dependencies of configuration ':myApplication2:classpath' after it has been resolved.
Working structure (with upper case sub project)
android-multi-project-sample
+ .gralde
+ .idea
+ app
+ build
+ gradle
+ MyApplication2 // upper case!!!!!!
- .gitignore
- android-multi-project-sample.iml
- build.gradle
- gradle.properties
- gradlew
- gradlew.bat
- local.properties
- settings.gradle
also the top level settings.gradle has to be changed:
+ include ':app', ':MyApplication2:mylibrary'
- include ':app', ':myApplication2:mylibrary'
and app/build.gradle has to change this
+ compile project(':MyApplication2:mylibrary')
- compile project(':myApplication2:mylibrary')
Everything compiles
Be careful! Git is not case sensitive by default. Use
git mv -f myApplication2 temp
git mv -f temp MyApplication2
to rename the folder.
According to official documentation on instant run.
What happened behind the scenes is that we have updated your project’s build.Gradle file to use the latest version of the Android Gradle plug-in, which is required for Instant Run to work. We also update your Gradle wrapper version to 2.8, and attempt to update the build tools version in all your modules to the latest (23.0.2). This isn't required for Instant Run, but it will use a new faster version of dex, which helps both instant run and a full build be a bit faster.
A Snippet of Application\build.gradle is shown below:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.0.0-alpha1'
}
}
Known Issues Using Instant Run
Using Instant Run with Reflection
Reflection could show unexpected things, for example:
Classes are all made public
Many other things are also made public
Limitations with Performance Profiling
We suggest temporarily disabling Instant Run while profiling your debug application.
There is a very small performance impact when using Instant Run, and a slightly larger impact when methods are overridden.
Increases in App Methods
Instant Run adds some methods–140 plus three times the number of classes in your app and its local dependencies. If the app was previously just below the dex limit, enabling Instant Run may push your app over the dex limit. Learn how to fix this by Optimizing Multi dex Development Builds.
Other Known Issues
Intermittent issues may occur where the IDE loses connection with the app which will trigger a full rebuild.
Third party Gradle plugin compatibility has not yet been tested, especially those that have not been updated to use the new transforms API.
Data-binding is currently broken in this build (capability to be restored).
so if you are facing this issue then you can turn off you instant run
go to Settings → Build, Execution, Deployment → Instant Run and uncheck Enable Instant Run… .
Better understanding of instant run go here
Take your dependencies out of your top level build gradle. As it is you are creating a classpath with your top level gradle and then attempting to overwrite it with your other build.gradles
From:
buildscript {
repositories {
mavenCentral()
jcenter()
maven { url 'https://maven.fabric.io/public' }
}
dependencies {
classpath 'com.android.tools.build:gradle:2.0.0-alpha6'
classpath 'com.novoda:bintray-release:0.2.7'
classpath 'io.fabric.tools:gradle:1.+'
}}
To: Note I did not add that commented line, Android-Studio does this automatically
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.0.0-alpha6'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
}
}
You should be able to add any needed Maven repositories into your separate app gradles, as they should be specific and the jcenter would cover many of these, as #AndroidMechanic, and #Hi I'm Frogatto have been trying to say in previous answers and comments.
Have a look at read here Bintray - JCenter
The other thing is, I do not understand why you are managing your libraries build gradle within your project as part of your project. You should be referencing your library from your project, with the app build.gradle. You are treating the library gradle as the app gradle.
dependencies {
compile fileTree(include: '*.jar', dir: 'libs')
compile 'com.android.support:support-v4:23.1.0'
compile 'com.android.support:appcompat-v7:23.1.0'
testCompile 'junit:junit:4.12'
}
Make these changes, then see what duplicates and you can manage that from there.
Also, I recommend manually syncing project with gradle files when changes are made. I would not rely on instant anything, it's important to make changes step wise and take stock of what's occurring, particularly when it won't compile. That's my opinion only and one way to program in android.
If instant run creates havoc with a particular project, I would disable it for that project. It is enabled by default and I've had no issues with it. The build mess may be the result of unclear gradles in your project to begin with.
Also:
In gradle wrapper properties, grade 2.10 is required for classpath 'com.android.tools.build:gradle:2.0.0-alpha6':
distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
See here for latest updates
Android Tools Project Site
Or you can install a previous version of Android Studio and use the previous working version of your project.
If you have multiple git files, I suggest you remove the redundant ones, keep only the ones you are using for version control.
classpath 'com.android.tools.build:gradle:2.0.0-alpha1'
try to change it to
classpath 'com.android.tools.build:gradle:2.0.0-alpha6'
alpha1 seems obsolete since today (?) and is not compiling any more.
Also you'll have to upgrade your gradle to latest 2.10 to work with alpha6
Two things you can try
Change your plugin for "android"
With the new gradle tools you need to specify the correct plugin for your module gradle file as well as your library gradle file. If you look closely, your library gradle file is correct:'
apply plugin: 'com.android.library'
Change your module gradle plugin:
apply plugin: "android" -> apply plugin: 'com.android.application'
org.apache classes are now depcrated
This could also be a possible reason as to why your application isn't compiling anymore. Remove this:
useLibrary 'org.apache.http.legacy'
See Deprecated List.
The library project's build.gradle seems to cause the configuration error (because of some obscure reason). For me it was enough to also add the library project (which is a git submodule) to settings.gradle instead of only adding the library's project module.
Instead of:
include ':libraries:my_library:sdk'
try including both the library subproject and the subproject's module:
include ':libraries:my_library'
include ':libraries:my_library:sdk'
Just when I'd achieved an effective development and build environment with the android-maven-plugin, the new kid on the block, Gradle, starts making inroads into the Android circles. Not being hot on Groovy and with the android-gradle plugin almost as fragmented as the OS itself I've hit some issues. Specifically around building library projects, with flavours and our buddy Robolectric.
Short version
I am at a loss as to what my next move should be upon encountering the gradle error;
Cannot add a SourceSet with name 'testDebug' as a SourceSet with that name already exists.
The error emanates from having productFlavours on a library (i.e. moving to the 0.9.2 android build system) and the gradle-android-test-plugin recently forked by the team over at Robolectric from Jake's creation (see here). I have followed all lines of investigation to near exhaustion and can report that the meer existence of the 'android-test' plugin within my library gradle file sends things awry.
Longer version
Here is the abridged application build.gradle file with pertinent information retained;
apply plugin: 'android-library'
apply plugin: 'android-test'
...
android {
compileSdkVersion 19
buildToolsVersion '19.0.3'
defaultConfig {
minSdkVersion 18
targetSdkVersion 19
versionCode buildNumber().toInteger()
versionName "1.0.0"
}
productFlavors {
estimote {
dependencies {
compile '<flavour specific dependency>'
}
}
radius {
dependencies {
compile '<flavour specific dependency>'
}
}
}
}
...
dependencies {
compile 'com.squareup.dagger:dagger:1.2.1'
compile 'com.squareup.dagger:dagger-compiler:1.2.1'
compile 'com.google.code.gson:gson:2.2.+'
// Testing dependencies
androidTestCompile 'org.mockito:mockito-core:1.9.5'
androidTestCompile 'com.squareup:fest-android:1.0.7'
androidTestCompile 'org.hamcrest:hamcrest-all:1.3'
androidTestCompile 'org.robolectric:robolectric:2.2'
androidTestCompile 'junit:junit:4.11'
}
And here is the abridged root build.gradle file.
buildscript {
repositories {
mavenLocal()
mavenCentral()
maven {
url 'https://oss.sonatype.org/content/repositories/snapshots'
}
}
dependencies {
classpath 'com.android.tools.build:gradle:0.9.2'
classpath 'org.robolectric.gradle:gradle-android-test-plugin:0.9.+'
}
}
allprojects {
repositories {
mavenLocal()
mavenCentral()
maven {
url 'https://oss.sonatype.org/content/repositories/snapshots'
}
}
}
If you've got this far down the page, give yourself a pat on the back. Now, the eagle eyed amongst you have probably noticed the omission on the sourceSets redirection with commands akin to;
sourceSets {
androidTest {
setRoot('src/test')
}
}
After the initial error is corrected these lines will need to be reinstated to inform gradle of the project's structure. The project's structure is standard and looks like;
- project_name
+ gradle
- lib
+ flavour1
+ flavour2
- main
+ java
- test
+ java
build.gradle
build.gradle
gradle.properties
settings.gradle
What is being used
The app is using gradle-1.10-all, 0.9.2 android-gradle plugin and 0.9.+ gradle-android-test-plugin.
The question
How should the project be set-up/changed to facilitate Robolectric testing on a library with flavours? Is this even possible yet?
I ran into the same issue, dug into the code, fixed it, and submitted a pull request which has just now been merged. See my explanation on the PR for details, but it boils down to a bad optimization in the plugin code:
https://github.com/robolectric/robolectric-gradle-plugin/pull/70
As of today you need to clone the repo and build and install the plugin to your local maven repo. The next time they do a release to maven central (perhaps release 0.13.1?), you'll be able to use the plugin directly from there.
I first added the android support library and tested that I could use it. However when I add Android Better Pickers in this maven repository I get the following error:
Gradle 'bumble' project refresh failed: Could not find
com.google.android:support-v4:18. Required by: myapp:app:unspecified
com.doomonafireball.betterpickers:library:1.4.2
This is how I set up my dependencies in the build.gradle located in MyProject -> app.
dependencies {
compile 'com.android.support:support-v4:18.0.+'
compile 'com.doomonafireball.betterpickers:library:1.4.2'
}
Android Better Pickers has the following in it's build.gradle and is packaged as an aar.
dependencies {
compile 'com.android.support:support-v4:18.0.+'
compile 'com.nineoldandroids:library:2.4.0'
}
Anyone know of a solution?
EDIT
Android better pickers now has gradle support since v 1.5! Now it is really easy adding it as a library, just follow there guide and don't forget to do a clean AND gradle sync after you change your build.gradle. Parts of the answers to this question still applies for none gradle projects I however.
First Make sure your are pointing to right sdk in File >Project Structure >Android SDK
In order to use Support Jar you have to install Android Support Repository from SDK Manager. SDK manager icon is available in Android Studio tool bar.
Things you should know for knowledge :
1.There is no need to add any dependency in your main module, if that is already added in any one of your library module already. So remove support dependency from your main module.
Make it something like this :
dependencies {
compile 'com.doomonafireball.betterpickers:library:1.4.2'
}
2.There is some issue going on in dependency management in android studio (0.4.2) which is fixed for Android Studio (0.4.3) but till the release check this as well For any dependency related issues.
Import Google Play Services library in Android Studio
EDIT :
I have checked the github repository there is no gradle dependency for date picker.
So do the following
Download Repository from github
Copy the library directory inside root of your project or make a directory and keep all your libraries inside that.The below configuration is for direct in root and I have renamed "library "to datepickerlibrary
Modify the build.gradle comes with library
build.gradle inside data picker library module
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.5.+'
}
}
apply plugin: 'android-library'
android {
compileSdkVersion 17
buildToolsVersion '19.0.0'
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
res.srcDirs = ['res']
}
}
}
apply plugin: 'maven'
apply plugin: 'signing'
version = "1.4.0"
isReleaseVersion = !version.endsWith("SNAPSHOT")
group = "com.doomonafireball.betterpickers"
repositories {
mavenCentral()
}
dependencies {
compile 'com.android.support:support-v4:18.0.+'
compile 'com.nineoldandroids:library:2.4.0'
}
Dependency in your main module's build.gradle should be like :
dependencies {
compile project(':datepickerlibrary') //if it is inside some sub directory you can give path like ':libraries:datepickerlibrary' depends on you
}
Add this line inside settings.gradle which is located in root of your Project directory:
include ':datepickerlibrary'
After these all checks, Do sync your project with gradle.
It worked for me, let me know if any issue comes.
ORIGINAL ASKER'S NOTES
I ended up doing something similar to the above and it worked great! What I did as a summary:
Downloaded and manually added the library as a dependency in Android Studio
Removed the following from the library's build.gradle (got a sonytype class not found exception or similar)
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
repository(url: sonatypeRepo) {
authentication(userName: sonatypeUsername,
password: sonatypePassword)
}
Updated the library's SDK version to match the one I had installed.