How to run copy task with android studio into assets folder - gradle

So far I have added the following to the end of my "build.gradle"
task copyFiles(type: Copy)
copyFiles {
description = 'Copies html5 files from the common library...'
from '../../www'
into 'assets/www'
include('**/*')
}
Now I just need some help on how o make this task get executed everytime (before) compiling the android source. I can run the copy task manually from command line, but Id like to have it run when I click "run" in android studio.
With the help of suggestion below, I have added
clean.dependsOn copyFiles
clean.mustRunAfter copyFiles
And with this addition I can get my copy task to run by doing rebuild -> run.
It's better than nothing but it would be nice to skip the rebuild step.
Here is the whole build.gradle that im using with android studio.
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.5.+'
}
}
apply plugin: 'android'
dependencies {
compile files('/libs/acra-4.3.0.jar')
}
android {
compileSdkVersion 17
buildToolsVersion "17"
defaultConfig {
minSdkVersion 8
targetSdkVersion 17
}
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src','libs']
resources.srcDirs = ['src']
aidl.srcDirs = ['src']
renderscript.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets']
}
instrumentTest.setRoot('tests')
}
}
task copyFiles(type: Copy)
copyFiles {
description = 'Copies html5 files from the common library...'
from '../../www'
into 'assets/www'
include('**/*')
}
clean.dependsOn copyFiles
clean.mustRunAfter copyFiles

This way I do custom copying of file assets in my android-gradle build system
preBuild.dependsOn copyFiles

Here is the module's build.gradle that I am using which successfully copies the files that I wanted as a pre-build task. The "into" is modelled after the File class in Java, so it should be familiar on how to use it. The two lines at the end is optional - it will run the copyFiles task when invoking gradle clean:
android {
.....
}
task copyFiles(type: Copy) {
description = 'copying some file(s)....'
from 'src/main'
into project(':Path:To:ModuleFrom:Settings.gradle').file('./res')
include 'file1.suffix'
include '**/*.html'
}
project.afterEvaluate {
preBuild.dependsOn copyFiles
}
clean.dependsOn copyFiles
clean.mustRunAfter copyFiles

I had a very similar problem to yours and I was able to solve it as follows:
android.buildTypes.all{ buildType ->
task "${buildType.name}CopyFiles" (type: Copy)
"${buildType.name}CopyFiles" {
description = 'Copies html5 files from the common library...'
from '../../www'
into 'assets/www'
include('**/*')
}
tasks.getByPath(":${project.name}:assemble${buildType.name.capitalize()}").dependsOn "${buildType.name}CopyFiles"
}
The problem is, that Android Studio seems to call a specific assemble task like assembleDebug when you click on run, that's why you have to make sure to make all assemble tasks depend on your copy task.

task myCopyToAssets(type: Copy) {
def toDir = rootProject.file('app/assets')
from (rootProject.file('app/usb')) {
include 'libhotplug.so'
}
into toDir
}
tasks.whenTaskAdded { task ->
//println task.getName()
if (task.name == 'assembleDebug' || task.name == 'assembleRelease') {
println 'myCopy'
myCopyToLibs.execute()
myCopyToAssets.execute()
}
}

Try this below your build.gradle:
tasks.whenTaskAdded { task ->
if (task.name == 'assemble') {
task.dependsOn copyFiles
}
}
In my case I manipulate some 'token' values inside res/values/strings.xml, and then copy it into ${project_root}/build/filtered-resources due to project cleaning issue.
To work correctly with this manipulated resource, android.sourceSets.res should be redefined to copied folder.
For your case copy assets folder with your www resource into ${PROJECT_ROOT}/build/your/desired/location, and asign android.sourceSets.assets point to it.

I use the following copy task in my project to copy strings into another directory:
task copyStringsUniversal(type: Copy) {
from 'src/main/res/values'
include 'strings.xml'
include 'array.xml'
into 'src/universal/res/values'
}
build.dependsOn copyStringsUniversal

Add this line to your build.gradle file:
assemble.dependsOn copyFiles
assemble.mustRunAfter copyFiles
where assemble can be any task.
Edit: I added the mustRunAfter bit to make sure the copyFiles task is run before any of the other assemble dependencies.

Related

How do I get my custom gradle tasks to run?

I have a gradle project from which I want to generate two artifacts - a java jar, and a tarball of additional files.
So I added the following to my build.gradle
def serviceName = "kafka-schemas"
task packageDistribution(type: Copy) {
from "$buildDir/resources/main"
include "*.avsc"
into "$buildDir/schemas"
}
task archive(type: Tar) {
dependsOn 'packageDistribution'
compression = 'GZIP'
from("$buildDir/schemas") {
include "**/*.avsc"
}
into("${serviceName}")
}
project.tasks.findByName('build') dependsOn archive
project.tasks.findByName('build') dependsOn packageDistribution
However when I run gradle clean build it does not run my tasks.
What am I doing wrong?
Try this:
processResources.dependsOn('packageDistribution')
task packageDistribution(type: Zip) {
archiveFileName = "xxxxx.zip"
destinationDirectory = file("$buildDir/dist")
from "xxxx"
}

Gradle task to create a zip archive of a directory

I have a gradle task to create a zip archive of a directory.
The gradle task is:
task archiveReports(type: Zip) {
from '/projects/Reports/*'
archiveName 'Reports.zip'
}
When I am running the command 'gradle archiveReports', its showing the build is successful. However, no zip file is getting created.
Am I missing something here?
I figured out a way for this:
Its working for me now.
task myZip(type: Zip) {
from 'Reports/'
include '*'
include '*/*' //to include contents of a folder present inside Reports directory
archiveName 'Reports.zip'
destinationDir(file('/dir1/dir2/dir3/'))
}
With Gradle 6.7,
task packageDistribution(type: Zip) {
archiveFileName = "my-distribution.zip"
destinationDirectory = file("$buildDir/dist")
from "$buildDir/toArchive"
}
Note : archiveName is deprected.
With Kotlin DSL
tasks.register<Zip>("packageDistribution") {
archiveFileName.set("my-distribution.zip")
destinationDirectory.set(layout.buildDirectory.dir("dist"))
from(layout.buildDirectory.dir("toArchive"))
}
With Groovy
tasks.register('packageDistribution', Zip) {
archiveFileName = "my-distribution.zip"
destinationDirectory = layout.buildDirectory.dir('dist')
from layout.buildDirectory.dir("toArchive")
}
Taken from the official docs
Just in case anyone will come here to find out how to zip your project e.g. to use it as an AWS lambda zip, here you go:
tasks {
val zipTask by register("createZip", Zip::class) {
from(processResources)
from(compileKotlin)
archiveFileName.set("app.zip")
into("lib") {
from(configurations.runtimeClasspath)
}
}
build {
dependsOn(zipTask)
}
}

How to run a Gradle task after apks are produced in Android Studio?

The following task (in build.gradle of an app's module) seems to run always before the apk is produced:
android.applicationVariants.all { variant ->
if (variant.buildType.name == 'release') {
def releaseBuildTask = tasks.create(name: "debug") {
println(".................... test ..............................")
}
releaseBuildTask.mustRunAfter variant.assemble
}
}
Could anyone offer a tip on how to run a task after the apks are produced?
Android tasks are typically created in the "afterEvaluate" phase.
Starting from gradle 2.2, those tasks also include "assembleDebug" and
"assembleRelease". To access such tasks, the user will need to use an
afterEvaluate closure:
afterEvaluate {
assembleDebug.dependsOn someTask
}
source: https://code.google.com/p/android/issues/detail?id=219732#c32
try add this in you app/build.gradle
assembleDebug.doLast {
android.applicationVariants.all { variant ->
if (variant.buildType.name == 'release') {
def releaseBuildTask = tasks.create(name: "debug") {
println(".................... test ..............................")
}
releaseBuildTask.mustRunAfter variant.assemble
}
}
println "build finished"
}
invoke the build command and specify the task assembleDebug
./gradlew assembleDebug
I found a solution that works, to copy the release APK into the project root automatically on build completion.
android {
...
task copyReleaseApk(type: Copy) {
from 'build/outputs/apk'
into '..' // Into the project root, one level above the app folder
include '**/*release.apk'
}
afterEvaluate {
packageRelease.finalizedBy(copyReleaseApk)
}
}

Extracting files downloaded as a dependency in Gradle

I've got a gradle script that goes something like the following:
apply plugin: 'java'
apply plugin: 'maven'
defaultTasks 'build'
ext.basedir = file('.').getAbsolutePath()
repositories{
maven { url "http://package.repo.com:8081/nexus/content/repository
}
configurations.all {
// check for updates every build
resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
}
dependencies {
compile group:'com.repo.wwpd', name:'kernel_utilities', version:'3.0.0', changing:true
}
task copy_dependencies(type: Copy) {
from configurations.compile
into basedir+'\\install'
include '*'
{ FileTree ioTree = fileTree(dir: "C:\\Users\\username\\install") }
ioTree.each { f ->
copy {
from tarTree(resources.gzip(f))
into "C:\\Users\\user\\test"
}
}
}
The goal is to get the dependencies, move them to the install folder, and extract them from the tar files to the test folder.
The problem appears to be that the task is executed before the dependencies are downloaded. So if the files already exist in install it works fine, but if the install folder is empty the result is an empty test folder but a full install folder.
[EDIT - updated with comments Peter N.]
This should be one way to solve your case ; note it contains two tasks, choose the one(s) that fulfill your needs: simple copy VS full extraction
def installDir = "${buildDir}/install"
def extractDir = "${buildDir}/extract"
// task to copy dependencies
task copyDependencies(type: Copy) {
from configurations.compile
into installDir
}
// task to extract dependencies
task extractDependencies(type: Copy) {
from configurations.compile.collect{tarTree (it)}
into extractDir
}

how can I override source dirs in gradle BUT only for this one annoying subproject

We have one main project and two subprojects. One of the subprojects is the playframework which has a "unique" build structure. How can I override the source directories BUT only for that one subproject such that all other projects are using the standard layout of source directories src/main/java, etc.
I tried the first answer which is not working and for my directory structure
stserver
build.gradle (1)
project1
webserver
build.gradle (2)
The 2nd gradle file is this
sourceSets.main{
java.srcDirs = ['app']
}
task build << {
println "source sets=$sourceSets.main.java.srcDirs"
}
When I run this, it prints out stserver/app as my srcDir instead of stserver/webserver/app???? What am I doing wrong here?
thanks,
Dean
Please have a look at the docs Peter has suggested. I have a ready build.gradle that I have working with Play Framework 2.0~, so I'll share it here in hope you'll find some useful setup tips.
My project structure:
+- master/
+- build.gradle <-- contains common setup,
and applies 'java' plugin to all subprojects
+- ui/ <-- project using Play framework
+- build.gradle <-- excerpt from this file is posted below
The excerpt from build.gradle
repositories{
maven{
//Play dependencies will be downloaded from here
url " http://repo.typesafe.com/typesafe/releases"
}
}
//Optional but useful. Finds 'play' executable from user's PATH
def findPlay20(){
def pathEnvName = ['PATH', 'Path'].find{ System.getenv()[it] != null }
for(path in System.getenv()[pathEnvName].split(File.pathSeparator)){
for(playExec in ['play.bat', 'play', 'play.sh']){
if(new File(path, playExec).exists()){
project.ext.playHome = path
project.ext.playExec = new File(path, playExec)
return
}
}
}
throw new RuntimeException("""'play' command was not found in PATH.
Make sure you have Play Framework 2.0 installed and in your path""")
}
findPlay20()
configurations{
//Configuration to hold all Play dependencies
providedPlay
}
dependencies{
providedPlay "play:play_2.9.1:2.0+"
//Eclipse cannot compile Play template, so you have to tell it to
//look for play-compiled classes
providedPlay files('target/scala-2.9.1/classes_managed')
//other dependencies
}
sourceSets.main{
java.srcDirs = ['app', 'target/scala-2.9.1/src_managed/main']
//Make sure Play libraries are visible during compilation
compileClasspath += configurations.providedPlay
}
//This task will copy your project dependencies (if any) to 'lib'
//folder, which Play automatically includes in its compilation classpath
task copyPlayLibs(type: Copy){
doFirst { delete 'lib' }
from configurations.compile
into 'lib'
}
//Sets up common play tasks to be accessible from gradle.
//Can be useful if you use gradle in a continuous integration
//environment like Jenkins.
//
//'play compile' becomes 'gradle playCompile'
//'play run' becomes 'gradle playRun', and so on.
[ ['run', [copyPlayLibs]],
['compile', [copyPlayLibs]],
['clean', []],
['test', []],
['doc', [copyPlayLibs]],
['stage', [copyPlayLibs]] ].each { cmdSpec ->
def playCommand = cmdSpec[0]
def depTasks = cmdSpec[1]
task "play${playCommand.capitalize()}" (type: Exec,
dependsOn: depTasks,
description: "Execute 'play ${playCommand}'") {
commandLine playExec, playCommand
}
}
//Interate playClean and playCompile task into standard
//gradle build cycle
clean.dependsOn "playClean"
[compileScala, compileJava]*.dependsOn "playCompile"
//Include Play libraries in Eclipse classpath
eclipse {
classpath {
plusConfigurations += configurations.providedPlay
}
}
Note: I have just extracted the above from an existing bigger gradle file, so it might be missing some things, so no guarantees:) Hope it's useful anyway. Good luck.

Resources