I'm getting this error in the console when clicking "Apply Code Changes" in Android Studio.
Changes were not applied.
Modifications to AndroidManifest.xml require an app restart.
Manifest 'AndroidManifest.xml' was modified.
However, I am not making any changes to the AndroidManifest.xml file. I verified the AndroidManifest.xml through git and no changes were made.
I have tried updating Android Studio and Gradle to the latest version, invalidating cache and rebuilding with no luck.
I experienced this same problem, it was caused by a third party gradle plugin.
To fix, try removing any gradle plugins that are run with your processManifest gradle task.
The reason apply changes is not working is when determining if apply changes can run, Android Studio looks at the merged manifest.xml file's last modified value. The gradle task process{buildVarient}Manifest when run will always update the last modified value of the merged manifest. Normally if nothing has changed in your manifest files then the task is skipped by gradle allowing apply changes to work. In my case a gradle plugin is likely causing the process manifest task to run.
To debug:
Build and install the app on your device as you would normally
Open the "Build" pane at the bottom of android studio and toggle the view to "Code mode" (the button below the green hammer)
Click the apply changes button to trigger another build
In the build pane you should see something like this
Executing tasks: [:app:assembleDebug]
...
> Task :app:mergeDebugResources UP-TO-DATE
> Task :app:javaPreCompileDebug UP-TO-DATE
> Task :app:createDebugCompatibleScreenManifests UP-TO-DATE
> Task :app:processDebugManifest
> Task :app:processBugsnagDebugManifest
> Task :app:processDebugResources
> Task :app:compileDebugJavaWithJavac UP-TO-DATE
> Task :app:compileDebugSources UP-TO-DATE
...
> Task :app:packageDebug
> Task :app:assembleDebug
BUILD SUCCESSFUL in 2s
132 actionable tasks: 5 executed, 127 up-to-date
Notice the app:processDebugManifest task is not marked UP-TO-DATE meaning it was run.
For me the problem was the Task :app:processBugsnagDebugManifest task which always runs by design, but also triggers the manifest to rebuild. Removing the Bugsnag gradle plugin fixed the problem for our app.
EDIT:
If your problem is with Bugsnag you can disable the plugin for build types instead of removing it entirely with:
android {
buildTypes {
debug {
...
ext.enableBugsnag = false
}
}
}
Related
Is there a clean way to run all test task for project Java dependencies in Gradle ? I noticed that Java dependencies only get their "jar" task run, and skip test / build.
main-code build.gradle
dependencies {
compile project(":shared-code")
}
gradle :main-code:build <-- Command that I want to run (that will also run :shared-code:tests , don't want to explicitly state it)
:shared-code:compileJava UP-TO-DATE
:shared-code:processResources UP-TO-DATE
:shared-code:classes
:shared-code:jar
<-- what actually gets run for shared-code (not missing build/tests)
** Best thing I can think of is a finalizeBy task on jar with test
UPD: Actually there is a task called buildNeeded
buildNeeded - Assembles and tests this project and all projects it depends on.
It will build an run tests of the projects your current project is dependent on.
OLD ANSWER:
Seems that gradle doesn`t do it out-of-box (tested on version 2.14.1). I came up with a workaround. build task triggers evaluation of a chain of other tasks which include testing phase.
testwebserver/lib$ gradle build --daemon
:testwebserver-lib:compileJava UP-TO-DATE
:testwebserver-lib:processResources UP-TO-DATE
:testwebserver-lib:classes UP-TO-DATE
:testwebserver-lib:jar UP-TO-DATE
:testwebserver-lib:assemble UP-TO-DATE
:testwebserver-lib:compileTestJava UP-TO-DATE
:testwebserver-lib:processTestResources UP-TO-DATE
:testwebserver-lib:testClasses UP-TO-DATE
:testwebserver-lib:test UP-TO-DATE
:testwebserver-lib:check UP-TO-DATE
:testwebserver-lib:build UP-TO-DATE
In order to force testing of dependency project (testwebserver-lib) for a dependent project (testwebserver) I added a task dependency in testwebserver/build.gradle:
...
compileJava.dependsOn ':testwebserver-lib:test'
dependencies {
compile project(':testwebserver-lib')
}
...
The problem is solved, read the last section.
The "background"
I'm making a ToDoApp just for a side project, as an excuse to learn Gradle. The initial build worked fine and the JAR worked as expected.[a]. But that version had no external dependencies; it was self-contained.
I was encouraged to add persistence to the project and I decided to use the GSON library (version 2.6.2) to work with JSON. I use IntelliJ IDEA (2016.1.2) to write code.
Now, I added the gson-2.6.2 artifact via the Maven Repository option in IntelliJ (in Project Structure). While writing the code, I added the library to the classpath of the project when prompted by IntelliJ. The code compiles and works fine when I run it in my IDE. Here's a sample run:
========ToDo App========
The following commands are recognised:
► help
Display this help message.
► add <name>
Add a new Todo task with the given name and also displays its corresponding ID.
► get <id>
Displays the task with the given id.
► mark <id>
Toggles the given task as completed or incomplete.
► print
Displays all tasks in order of their creation.
► update <id> <new text>
Updates the item with the given id to store the new text.
► del <id>
Deletes the task with the given id.
► exit
Exit the program.
The tasks are :
>> add Get the Gradle build to work.
New item added with id = 1
>> add Push the stable system to GitHub and wait for Travis to give the green signal.
New item added with id = 2
>> add Proceed
New item added with id = 3
>> print
The tasks are :
• Get the Gradle build to work. [ID: 1 Completed: false]
• Push the stable system to GitHub and wait for Travis to give the green signal. [ID: 2 Completed: false]
• Proceed [ID: 3 Completed: false]
>> exit
It works fine. The JSON data gets saved as I expect:
{"currentId":3,"toDos":{"1":{"id":1,"name":" Get the Gradle build to work. ","completed":false},"2":{"id":2,"name":" Push the stable system to GitHub and wait for Travis to give the green signal.","completed":false},"3":{"id":3,"name":" Proceed","completed":false}}}
When I rerun the code, the data is read back properly. I'm very happy with my code.
The "situation"
Here's my build.gradle:
group 'ml.cristatus'
version = '0.2'
apply plugin: 'java'
sourceCompatibility = 1.7
repositories {
mavenCentral()
}
dependencies {
compile 'com.google.code.gson:gson:2.6.2'
}
jar {
manifest {
attributes 'Main-Class': 'ml.cristatus.todo.ToDoApp'
}
}
When I run gradle build on my Ubuntu 16.04 terminal, the JAR file is built with the following output:
:compileJava
warning: [options] bootstrap class path not set in conjunction with -source 1.7
1 warning
:processResources UP-TO-DATE
:classes
:jar
:assemble
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test UP-TO-DATE
:check UP-TO-DATE
:build
BUILD SUCCESSFUL
Total time: 7.036 secs
This build could be faster, please consider using the Gradle Daemon: https://docs.gradle.org/2.13/userguide/gradle_daemon.html
So I somehow managed to make the thing compile. But when I try to run it, using java -jar build/libs/ToDoApp-0.2.jar, the code doesn't work:
========ToDo App========
Exception in thread "main" java.lang.NoClassDefFoundError: com/google/gson/Gson
at ml.cristatus.todo.repository.ToDoRepositoryWithJSON.<init>(ToDoRepositoryWithJSON.java:25)
at ml.cristatus.todo.ToDoApp.REPL(ToDoApp.java:38)
at ml.cristatus.todo.ToDoApp.main(ToDoApp.java:17)
Caused by: java.lang.ClassNotFoundException: com.google.gson.Gson
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 3 more
I'm probably making some newbie mistake, but I can't seem to be able to put my finger on it. What am I doing wrong? It is also interesting to note that the code compiles yet it can't find the gson artifact. I'm guessing it has something to do with the classpath? I don't know. I'm not sure.
Please help me in this regard.
Solution
I just added this line to the jar {} block:
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
Courtesy of this tutorial.
[a]Here's the version 0.1 binary.
You have to add jar file with gson jar to classpath. When you are starting application ("java -jar build/libs/ToDoApp-0.2.jar"). There is multiple ways it can be achiveved.
One possible way is:
Add task into your gradle, which copy dependencies (gson.jar in your case) into "lib" directory. And when you are starting your application, add it to classpath. For example in this way "java -cp build/lib/gson.jar -jar build/libs/ToDoApp-0.2.jar"
Maybe better for you will be:
Add dependencies into your manifest. It is discussed in this answer how to copy the dependencies libraries JARs in gradle
It should work for you.
Next Option is:
Create an "uberjar" it means add all dependencies into one big jar file. Personally I don't like it. But it will work in your case. How to create uberjar in gradle is here discussed here: Building a uberjar with Gradle
I have my grade script set up.
When I execute the Gradle build, everything is working and it runs the jUnit tests.
After that when I run the Gradle test I get the following:
C:\Users\..\..\Project>gradle test
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test UP-TO-DATE
When I perform gradle clean, then Gradle build works, of course...
I want to be able to reset only the tests, not build the whole project: how should I do this?
One option would be using the --rerun-tasks flag in the Forcing tasks to execute section. This would rerun all the the test task and all the tasks it depends on.
If you're only interested in rerunning the tests then another option would be to make gradle clean the tests results before executing the tests. This can be done using the cleanTest task.
Some background - the Java plugin defines a clean tasks to each of the other tasks. According to the Tasks documentation:
cleanTaskName - Deletes files created by specified task. cleanJar will delete the JAR file created by the jar task, and cleanTest will delete the test results created by the test task.
Therefore, all you need in order to re-run your tests is to also run the cleanTest task, i.e.:
gradle cleanTest test
Other option would be to add following in your build.gradle:
test.outputs.upToDateWhen {false}
This was recently the topic on Gradle's blog post Stop rerunning your tests. The author shows an example using outputs.upToDateWhen { false } and explains why it is wrong:
This doesn’t actually force reruns
What the author of this snippet probably wanted to say is “Always rerun my tests”. That’s not what this snippet does though. It will only mark the task out-of-date, forcing Gradle to recreate the output. But here’s the thing, if the build cache is enabled, Gradle doesn’t need to run the task to recreate the output. It will find an entry in the cache and unpack the result into the test’s output directory.
The same is true for this snippet:
test.dependsOn cleanTest
Gradle will unpack the test results from the build cache after the output has been cleaned, so nothing will be rerun. In short, these snippets are creating a very expensive no-op.
If you’re now thinking “Okay, I’ll deactivate the cache too”, let me tell you why you shouldn’t.
Then, the author goes on to explain why rerunning some tests is a waste of time:
The vast majority of your tests should be deterministic, i.e. given the same inputs they should produce the same result.
In the few cases where you do want to rerun tests where the code has not changed, you should model them as an input. Here are both examples from the blog post that show adding an input so the task will use it during its up-to-date checks.
task randomizedTest(type: Test) {
systemProperty "random.testing.seed", new Random().nextInt()
}
task systemIntegrationTest(type: Test) {
inputs.property "integration.date", LocalDate.now()
}
I recommend reading the entire blog post.
gradle test --rerun-tasks
Specifies that any task optimization is ignored.
Source: https://gradle.org/docs/current/userguide/gradle_command_line.html
--rerun-tasks works, but is inefficient as it reruns all tasks.
cleanTest by itself may not suffice due to build cache.
so, best way to accomplish this is:
./gradlew --no-build-cache cleanTest test
Here's a solution using the "build.gradle" file, in case you don't want to modify your command line:
test {
dependsOn 'cleanTest'
//Your previous task details (if any)
}
And here's the output. Notice 2 changes from your previous output:
1) A new 'cleanTest' task appears in the output.
2) 'test' is always cleaned (i.e. never 'UP-TO-DATE') so it gets executed every time:
$ gradle build
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:findMainClass
:jar
:bootRepackage
:assemble
:cleanTest
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test
:check
:build
Also,
having to add --rerun-tasks is really redundant. Never happens. Create a --no-rerun-tasks and make --rerun-tasks default when cleanTask
TL;DR
test.dependsOn cleanTest
None of the above methods worked for me.
What worked for me was simply removing all items from the cache directory in /Users/<username>/.gradle/caches/build-cache-1/.
I have the following project tree:
root
|
|--MP
| |
| |---build.gradle
|
|--API
|
|---build.gradle
|
|---settings.gradle
MP::buiild.gradle:
dependencies {
compile project(':API')
}
root:build.gradle:
subprojects{
apply plugin : 'java'
repositories{
mavenCentral()
}
version = '1.0'
jar{
manifest{
attributes 'Gradle': 'Multiproject'
}
}
}
root::settings.gradle:
include 'API', 'MP'
The thing is if we delete one of these three files gradle build task will fail. So it's not clear to me how java plugin builds the project. I run gradle build for MP::build.gradle, the following output was produced:
:API:compileJava
:API:processResources UP-TO-DATE
:API:classes
:API:jar
:MP:compileJava
:MP:processResources UP-TO-DATE
:MP:classes
:MP:jar
:MP:assemble
:MP:compileTestJava UP-TO-DATE
:MP:processTestResources UP-TO-DATE
:MP:testClasses UP-TO-DATE
:MP:test UP-TO-DATE
:MP:check UP-TO-DATE
:MP:build
So, the first what we need to do when we run gradle build for MP::build.gradle is to resolve all dependecies. As far as I understand it means to load jars from an external repositories and, if need, to compile jar-files from a separate projects. In my case it's just to get API project jar-file.
So my question is what is the subsequnce of actions to compile that jar. What will happens when gradle came across the compie project(':API'). It's looking for the gradle.settings file and report an error if there isn't or it's looking for build.gradle in the root directory first?
To have quick look of what is going on in a java multiproject:
http://www.gradle.org/docs/current/userguide/tutorial_java_projects.html
"For the subsequence of actions to compile that jar." Look at the diagram
http://www.gradle.org/docs/current/userguide/tutorial_java_projects.html
And for crossproject dependencies
http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:cross_project_configuration
Quote: "By default, the configuration of all projects happens before any task is executed"
I hope you have already figured it out .
So the gradle build life cycle explains it ... the life cycle is as below
1) initialisation
2) configuation
3) execuion .
for your particular case of a multi project build , what happens is
1) initialisation ::
here the settings.gradle is searched for no matter from which project you run it (it always tries to find settings.gradle file when you run a task and includes those projects defined in its include directive.)
2) configures
it creates the task tree based on the task you have tried to run and its dependencies.
3)execution ::
runs the task tree.
Please let me know if this is helpful.
You can read this page for more clarity.
http://www.gradle.org/docs/current/userguide/build_lifecycle.html
Gradle, being an incremental build system, is supposed to detect when no changes to source or outputs have been made, and skip tasks when appropriate to save on build time.
However, in my build, subsequent executions of a gradle task, with no changes in between, this incremental feature is not working. compileJava, jar, etc are executing with every build rather than only when changes have been made.
Our build is pretty complex (switching to gradle from a very old, very messy ant build), so I'm just going to show a small snippet:
buildDir = 'build-server'
jar {
sourceSets.main.java.srcDirs = ['src',
'../otherProject/src']
sourceSets.main.java {
include 'com/ourCompany/pkgone/allocation/**'
include 'com/ourCompany/pkgone/authenticationmngr/**'
...
//Excludes from all VOBs
exclude 'com/ourCompany/pkgtwo/polling/**'
}
sourceSets.main.resources.srcDirs = ['cotsConfig/ejbconfig']
sourceSets.main.resources {
include 'META-INF/**'
}
}
dependencies {
compile project(':common')
}
Running gradle jar on this project twice in a row results in the following output:
P:\Project>gradlew jar
:common:compileJava
:common:processResources UP-TO-DATE
:common:classes
:common:jar
:clnt:compileJava
:clnt:processResources UP-TO-DATE
:clnt:classes
:clnt:jar
BUILD SUCCESSFUL
Total time: 1 mins 46.802 secs
P:\Project>gradlew jar
:common:compileJava
:common:processResources UP-TO-DATE
:common:classes
:common:jar
:clnt:compileJava
:clnt:processResources UP-TO-DATE
:clnt:classes
:clnt:jar
BUILD SUCCESSFUL
My question is, what might I be doing that would prevent the up-to-date detection to not work properly? Could it be related to my complicated build path?
When you run with --info, Gradle will tell you why the task isn't up-to-date.
Two things you need to do
Check if your gradle version is above 2.1
There is a way setting incremental build:
tasks.withType(JavaCompile) {
options.incremental = true // one flag, and things will get MUCH faster
}
Reference is here: https://blog.gradle.org/incremental-compiler-avoidance