gradle clean in linux does not delete the contents of buildDir - linux

Gradle 2.13
Revision: 3b427b1481e46232107303c90be7b05079b05b1c
OS: Linux 3.10.0-327.36.3.el7.x86_64 amd64
In linux on calling the clean task the contents of buildDir path are not deleted whereas the same in windows deletes the contents of buildDir(expected behaviour). Whats the reason ?
Code sample
apply plugin : 'java'
ant.importBuild 'build.xml'
sourceCompatibility = 1.8
def projVersion = ant.properties['version']
def projName = "xyz"
def buildPath = "/home/test/build"
def dependencyPath = "/home/test/dependency"
buildDir = new File("$buildPath","$projName")
def serviceDirBin = new File(buildDir , 'bin')
def serviceDirConf = new File(buildDir , 'conf')
def serviceDirThirdparty = new File(buildDir , 'thirdparty')
repositories {
flatDir {
dirs file("$dependencyPath"),
}
}
sourceSets{
main{
java{
srcDir 'src'
}
output.classesDir 'classes'
}
test{
java {
srcDir 'src/test'
}
}
}
dependencies {
/*Some compile dependencies*/
}
jar{
destinationDir = new File(serviceDirThirdparty, 'lib')
baseName='xyz'
manifest {
'Build-Timestamp': new Date().format('yyyy-dd-MM HH:mm:ss'),
'Specification-Version': '1.0',
'Implementation-Version': "$projVersion"
}
}
task xyzpackager << {
copy{
from ("$buildPath/sf/distribution/bin")
into file(serviceDirBin)
}
copy{
from ('conf')
into file(serviceDirConf)
}
copy{
from configurations.compile
from configurations.runtime
into new File(serviceDirThirdparty,'lib')
}
}
test {
reports {
html.enabled = false
junitXml.enabled = true
junitXml.destination = file("TestReport/xml")
}
}
jar.doLast {
delete "$buildDir/tmp","$buildDir/dependency-cache","$buildDir/classes","$buildDir/libs"
}
compileTestJava.doLast{
delete "TestReport"
}
the jar is copied to thirdparty folder and the bin/conf folders have some other files. SO basically i want to delete the buildDir before every new build

Related

How to generate on the fly Java source code to build with Gradle in Android Studio?

As part of an Android app that uses the NDK, I need to export some constants from the C/C++ world into Java. For obvious reasons, I'd rather have this automated. I'm using Android Studio with the NDK support.
How can I generate some .java file on the fly from a shell script that would be ran by Gradle whenever the app builds? Ideally this .java file would go in an build intermediaries directory somewhere and wouldn't have to be in the app source directory.
As an example, the shell script would generate this Java source:
public enum Type {
FOO,
BAR
}
from this C++ source:
enum class Type {
FOO,
BAR
}
For reference here's a simplified version of the Gradle file I'm starting from in Android Studio:
apply plugin: 'com.android.model.application'
model {
compileOptions.with {
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
}
android {
compileSdkVersion = 23
buildToolsVersion = "23.0.2"
defaultConfig.with {
applicationId = "..."
minSdkVersion.apiLevel = 18
targetSdkVersion.apiLevel = 23
}
defaultConfig.multiDexEnabled = true
}
android.ndk {
platformVersion = "18"
moduleName = "jni"
...
}
android.buildTypes {
release {
minifyEnabled = false
proguardFiles.add(file('proguard-rules.txt'))
ndk.with {
CFlags.add("-Werror")
cppFlags.add("-Werror")
}
}
}
android.productFlavors {
create("arm7") {
ndk.abiFilters.add("armeabi-v7a")
}
}
}
repositories {
...
}
dependencies {
...
}
apply plugin: 'com.google.gms.google-services'
You could just write the generated file to the $buildDir/generatedJava then add that directory as a source folder. Then make the task javaCompile depend on your task that generates the source. Something like this could be used inside a build.gradle
def outputJavaFile = new File("$buildDir.absolutePath/generatedJava", 'MyEnum.java')
task generateSources(type: Exec) {
def source = $/
package com.example;
public enum Something {
One,
Two
}
/$
if (!outputJavaFile.parentFile.exists()) {
outputJavaFile.parentFile.mkdirs()
}
outputJavaFile.withWriter {
it << source
}
}
compileJava.dependsOn outputJavaFile
sourceSets {
main {
java {
srcDirs 'src/main/java', outputJavaFile.absolutePath
}
}
}
// if the goal is to generate the source from a script then just call the script
// inside the Exec closure
task shellScriptToGenerateSources(type: Exec) {
commandLine 'myShellScript.sh'
}
// then make compileJava depend on the task that runs the script
compileJava.dependsOn shellScriptToGenerateSources
Edit: To apply the same logic to your updated build.gradle file might look something like this
apply plugin: 'com.android.model.application'
// define an output folder for our generated .java files
def GENERATED_JAVA_OUTPUT = "$buildDir/generatedJava"
// if the goal is to generate the source from a script then just call the script
// inside the Exec closure
task shellScriptToGenerateSources(type: Exec) {
commandLine 'myShellScript.sh'
}
// then make compileJava depend on the task that runs the script
compileJava.dependsOn shellScriptToGenerateSources
model {
compileOptions.with {
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
}
android {
compileSdkVersion = 23
buildToolsVersion = "23.0.2"
defaultConfig.with {
applicationId = "..."
minSdkVersion.apiLevel = 18
targetSdkVersion.apiLevel = 23
}
defaultConfig.multiDexEnabled = true
}
android.ndk {
platformVersion = "18"
moduleName = "jni"
...
}
android.buildTypes {
release {
minifyEnabled = false
proguardFiles.add(file('proguard-rules.txt'))
ndk.with {
CFlags.add("-Werror")
cppFlags.add("-Werror")
}
}
}
android.productFlavors {
create("arm7") {
ndk.abiFilters.add("armeabi-v7a")
}
}
// let android know that our java sources shoudl also consider the generated java for the compiler
android.sourceSet {
main {
java {
srcDir(GENERATED_JAVA_OUTPUT)
}
}
}
}
repositories {
...
}
dependencies {
...
}
apply plugin: 'com.google.gms.google-services'

Gradle task dependencies on dynamically created tasks

I have a multiproject build where I need to publish some dependencies to a custom local Maven repository on disk and then add this folder to a distribution zip.
I define publishing tasks for each subproject using the maven-publish plugin.
subprojects {
apply plugin: 'maven-publish'
configurations {
offlineDependencies
}
publishing {
publications {
configurations.each { config ->
if (config.name == "offlineDependencies") {
def files = config.files
config.dependencies.each { dep ->
files.each { file ->
if (file.name == "${dep.name}-${dep.version}.jar") {
"${dep.name}"(MavenPublication) {
artifact (file) {
groupId = "${dep.group}"
artifactId = "${dep.name}"
version = "${dep.version}"
}
}
}
}
}
}
}
}
repositories {
maven {
name 'dependencies'
url '../build/repository'
}
}
}
}
Using the distribution plugin I create a zip file
distributions {
release {
baseName 'release'
contents {
from('src/main/resources/')
into("repository"){
from("$buildDir/repository")
}
}
}
}
How can I make sure that all the dynamically created publish tasks are run before creating the zip file?
I tried making a new task for all subprojects that depends on the dynamically created tasks, but it seems they're not created yet at that time.
subprojects {
task offlineDep << {
println 'Creating offline dependencies'
}
offlineDep.dependsOn {
tasks.findAll { task -> task.name.endsWith('PublicationToDependenciesRepository') }
}
}
I found a solution to this problem. By collecting the names of the artifacts and generating the tasknames I know will be created later and adding them as dependencies.
subprojects {
apply plugin: 'maven-publish'
def offlineDependencyNames = []
publishing {
publications {
configurations.each { config ->
if (config.name == "offlineDependencies") {
def files = config.files
config.dependencies.each { dep ->
files.each { file ->
if (file.name == "${dep.name}-${dep.version}.jar") {
offlineDependencyNames << dep.name
"${dep.name}"(MavenPublication) {
artifact (file) {
groupId = "${dep.group}"
artifactId = "${dep.name}"
version = "${dep.version}"
}
}
}
}
}
}
}
}
repositories {
maven {
name 'dependencies'
url "${rootProject.buildDir}/repository"
}
}
}
task publishOfflineDependencies
publishOfflineDependencies.dependsOn {
offlineDependencyNames.collect { name ->
"publish${name[0].toUpperCase()}${name.substring(1)}PublicationToDependenciesRepository"
}
}
}
releaseDistZip.dependsOn {
subprojects.collect {
p -> p.path + ':publishOfflineDependencies'
}
}

Facing issues while running cucumber with serenity

To integrate Cucumber with Serenity, I have created below Gardle file. Serenity is working fine, however I am not able to use it with Cucumber. When I use #RunWith(CucumberWithSerenity.class) in runner class, it gives me unresolved type error.
build.gradle:
apply plugin: "java"
apply plugin: "maven"
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'net.serenity-bdd.aggregator'
apply plugin: 'com.jfrog.bintray'
group = "myorg"
version = 1.0
repositories {
maven {
url "http://nexus2.sdmc.ao-srv.com/content/groups/inhouse_dit/"
}
}
buildscript {
repositories {
maven {
url "http://nexus2.sdmc.ao-srv.com/content/groups/inhouse_dit/"
}
}
dependencies {
classpath("net.serenity-bdd:serenity-gradle-plugin:1.0.47")
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:0.6'
}
}
ext {
bintrayBaseUrl = 'https://api.bintray.com/maven'
bintrayRepository = 'maven'
bintrayPackage = 'serenity-cucumber'
projectDescription = 'Serenity Cucumber integration'
if (!project.hasProperty("bintrayUsername")) {
bintrayUsername = 'wakaleo'
}
if (!project.hasProperty("bintrayApiKey")) {
bintrayApiKey = ''
}
serenityCoreVersion = '1.0.49'
cucumberJVMVersion = '1.2.2'
//versionCounter = new ProjectVersionCounter(isRelease: project.hasProperty("releaseBuild"))
}
sourceSets.all { set ->
def jarTask = task("${set.name}Jar", type: Jar) {
baseName = baseName + "-$set.name"
from set.output
}
artifacts {
archives jarTask
}
}
sourceSets {
api
impl
}
dependencies {
apiCompile 'commons-codec:commons-codec:1.5'
implCompile sourceSets.api.output
implCompile 'commons-lang:commons-lang:2.6'
compile "info.cukes:cucumber-java:${cucumberJVMVersion}"
compile "info.cukes:cucumber-junit:${cucumberJVMVersion}"
testCompile 'net.serenity-bdd:core:1.0.47'
testCompile 'net.serenity-bdd:serenity-junit:1.0.47'
testCompile('junit:junit:4.11')
testCompile('org.assertj:assertj-core:1.7.0')
testCompile('org.slf4j:slf4j-simple:1.7.7')
testCompile sourceSets.api.output
testCompile sourceSets.impl.output
testCompile 'org.codehaus.groovy:groovy-all:2.3.6'
testCompile("org.spockframework:spock-core:0.7-groovy-2.0") {
exclude group: "junit"
exclude module: "groovy-all"
}
testCompile("com.github.goldin:spock-extensions:0.1.4") {
exclude module: "spock-core"
exclude module: "slf4j-api"
}
runtime configurations.apiRuntime
runtime configurations.implRuntime
}
gradle.startParameter.continueOnFailure = true
jar {
from sourceSets.api.output
from sourceSets.impl.output
manifest {
attributes("Implementation-Title": "Serenity Cucumber Plugin",
"Implementation-Version": project.version.toString())
}
}
task sourcesJar(type: Jar, dependsOn: classes) {
classifier = 'sources'
from sourceSets.main.allSource
}
task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
}
artifacts {
archives sourcesJar, javadocJar
}
bintray {
user = bintrayUsername //this usually comes form gradle.properties file in ~/.gradle
key = bintrayApiKey //this usually comes form gradle.properties file in ~/.gradle
publications = ['mavenJava'] // see publications closure
pkg {
repo = 'maven'
userOrg = 'serenity'
name = 'serenity-cucumber'
desc = 'Serenity Cucumber integration'
licenses = ['Apache-2.0']
labels = ['serenity','bdd','cucumber']
}
}
uploadArchives {
repositories {
mavenDeployer {
repository(url: uri("${buildDir}/repo"))
addFilter("main") { artifact, file -> artifact.name == project.name }
["api", "impl"].each { type ->
addFilter(type) { artifact, file -> artifact.name.endsWith("-$type") }
// We now have to map our configurations to the correct maven scope for each pom
["compile", "runtime"].each { scope ->
configuration = configurations[type + scope.capitalize()]
["main", type].each { pomName ->
pom(pomName).scopeMappings.addMapping 1, configuration, scope
}
}
}
}
}
}
task wrapper (type: Wrapper) {
gradleVersion = '2.3'
distributionUrl = 'http://nexus2.sdmc.ao-srv.com/content/repositories/inhouse_dit_thirdparty/org/gradle/gradle-bin/2.3/gradle-2.3-bin.zip'
}
Please suggest what I need to change to run serenity with Cucumber. Thanks in advance.
You need to add serenity-cucumber to your dependencies:
testCompile 'net.serenity-bdd:serenity-cucumber:1.0.17'
Following line fixed the issue for me (gradle 4.10):
testCompile group: 'net.serenity-bdd', name: 'serenity-cucumber', version: '1.9.40'

ndk-build.cmd: command not found 3

Error:Execution failed for task ':imagepipeline:ndk_build_bitmaps'.
A problem occurred starting process 'command 'ndk-build.cmd''
How to solve?The problem with for a long time, don't know how to do?For the great spirit guide
apply plugin: 'com.android.library'
apply plugin: 'maven'
project.group = GROUP
version = VERSION_NAME
apply plugin: 'org.robolectric'
apply plugin: 'de.undercouch.download'
import de.undercouch.gradle.tasks.download.Download
import org.apache.tools.ant.taskdefs.condition.Os
dependencies {
provided "com.google.code.findbugs:jsr305:${JSR_305_VERSION}"
compile "com.parse.bolts:bolts-android:${BOLTS_ANDROID_VERSION}"
compile "com.nineoldandroids:library:${NINEOLDANDROID_VERSION}"
compile "com.android.support:support-v4:${SUPPORT_V4_VERSION}"
provided "javax.annotation:javax.annotation-api:${ANNOTATION_API_VERSION}"
compile project(':fbcore')
testCompile "com.google.guava:guava:${GUAVA_VERSION}"
testCompile "junit:junit:${JUNIT_VERSION}"
testCompile "org.mockito:mockito-core:${MOCKITO_CORE_VERSION}"
testCompile "org.powermock:powermock-api-mockito:${POWERMOCK_VERSION}"
testCompile "org.powermock:powermock-module-junit4-rule:${POWERMOCK_VERSION}"
testCompile "org.powermock:powermock-classloading-xstream:${POWERMOCK_VERSION}"
testCompile("org.robolectric:robolectric:${ROBOLECTRIC_VERSION}") {
exclude group: 'commons-logging', module: 'commons-logging'
exclude group: 'org.apache.httpcomponents', module: 'httpclient'
}
}
apply from: rootProject.file('release.gradle')
// We download various C++ open-source dependencies from SourceForge into nativedeps/downloads.
// We then copy both downloaded code and our custom makefiles and headers into nativedeps/merge.
def nativeDepsDir = new File("${projectDir}/nativedeps")
def downloadsDir = new File("${nativeDepsDir}/downloads")
def mergeDir = new File("${nativeDepsDir}/merge")
task createNativeDepsDirectories {
nativeDepsDir.mkdirs()
downloadsDir.mkdirs()
mergeDir.mkdirs()
}
task downloadGiflib(dependsOn: createNativeDepsDirectories, type: Download) {
src 'http://downloads.sourceforge.net/project/giflib/giflib-5.1.1.tar.gz'
onlyIfNewer true
overwrite false
dest downloadsDir
}
task downloadLibjpeg(dependsOn: createNativeDepsDirectories, type: Download) {
src 'http://downloads.sourceforge.net/project/libjpeg-turbo/1.3.1/libjpeg-turbo-1.3.1.tar.gz'
onlyIfNewer true
overwrite false
dest downloadsDir
}
task downloadLibpng(dependsOn: createNativeDepsDirectories, type: Download) {
src 'http://downloads.sourceforge.net/project/libpng/libpng16/older-releases/1.6.10/libpng-1.6.10.tar.gz'
onlyIfNewer true
overwrite false
dest downloadsDir
}
task downloadLibwebp(dependsOn: createNativeDepsDirectories, type: Download) {
src 'https://github.com/webmproject/libwebp/archive/v0.4.2.tar.gz'
onlyIfNewer true
overwrite false
dest downloadsDir
}
task unpackGiflib(dependsOn: downloadGiflib, type: Copy) {
from tarTree(resources.gzip("${downloadGiflib.dest}/giflib-5.1.1.tar.gz"))
into "${downloadsDir}"
}
task unpackLibjpeg(dependsOn: downloadLibjpeg, type: Copy) {
from tarTree(resources.gzip("${downloadLibjpeg.dest}/libjpeg-turbo-1.3.1.tar.gz"))
into "${downloadsDir}"
}
task unpackLibpng(dependsOn: downloadLibpng, type: Copy) {
from tarTree(resources.gzip("${downloadLibpng.dest}/libpng-1.6.10.tar.gz"))
into "${downloadsDir}"
}
task unpackLibwebp(dependsOn: downloadLibwebp, type: Copy) {
from tarTree(resources.gzip("${downloadLibwebp.dest}/v0.4.2.tar.gz"))
into "${downloadsDir}"
}
task copyGiflib(dependsOn: unpackGiflib, type: Copy) {
from "${unpackGiflib.destinationDir}/giflib-5.1.1/lib"
from 'src/main/jni/third-party/giflib'
include('*.c', '*.h', '*.mk')
into "${mergeDir}/giflib"
}
task copyLibjpeg(dependsOn: unpackLibjpeg, type: Copy) {
from "${unpackLibjpeg.destinationDir}/libjpeg-turbo-1.3.1"
from 'src/main/jni/third-party/libjpeg-turbo-1.3.x'
include('**/*.c', '**/*.h','**/*.S', '**/*.asm', '**/*.inc', '*.mk')
into "${mergeDir}/libjpeg-turbo-1.3.x"
}
task copyLibpng(dependsOn: unpackLibpng, type: Copy) {
from "${unpackLibpng.destinationDir}/libpng-1.6.10"
from 'src/main/jni/third-party/libpng-1.6.10'
include('**/*.c', '**/*.h', '**/*.S', '*.mk')
into "${mergeDir}/libpng-1.6.10"
}
task copyLibwebp(dependsOn: unpackLibwebp, type: Copy) {
from "${unpackLibwebp.destinationDir}/libwebp-0.4.2"
from 'src/main/jni/third-party/libwebp-0.4.2'
include('src/**/*.c', 'src/**/*.h', '*.mk')
into "${mergeDir}/libwebp-0.4.2"
}
task fetchNativeDeps(dependsOn: [copyGiflib, copyLibjpeg, copyLibpng, copyLibwebp]) {
}
task removeNativeDeps(type: Delete) {
delete nativeDepsDir
}
allclean.dependsOn removeNativeDeps
def getNdkBuildName() {
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
return "ndk-build.cmd"
} else {
return "ndk-build"
}
}
def getNdkBuildFullPath() {
// we allow to provide full path to ndk-build tool
if (hasProperty('ndk.command')) {
return property('ndk.command')
}
// or just a path to the containing directiry
if (hasProperty('ndk.path')) {
def path = property('ndk.path')
if (!path.endsWith(File.separator)) {
path += File.separator
}
return path + getNdkBuildName()
}
// if none of above is provided, we assume ndk-build is already in $PATH
return getNdkBuildName()
}
def makeNdkTasks(String name, Object[] deps) {
task "ndk_build_$name"(dependsOn: deps, type: Exec) {
inputs.file("src/main/jni/$name")
outputs.dir("$buildDir/$name")
commandLine getNdkBuildFullPath(),
'NDK_PROJECT_PATH=null',
'NDK_APPLICATION_MK=../Application.mk',
'NDK_OUT=' + temporaryDir,
"NDK_LIBS_OUT=$buildDir/$name",
'-C', file("src/main/jni/$name").absolutePath,
'--jobs', '8'
}
task "ndk_clean_$name"(type: Exec) {
ignoreExitValue true
commandLine getNdkBuildFullPath(),
'NDK_PROJECT_PATH=null',
'NDK_APPLICATION_MK=../Application.mk',
'NDK_OUT=' + temporaryDir,
"NDK_LIBS_OUT=$buildDir/$name",
'-C', file("src/main/jni/$name").absolutePath,
'clean'
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn "ndk_build_$name"
}
clean.dependsOn "ndk_clean_$name"
}
android {
def ndkLibs = [
['bitmaps', []],
['gifimage', [copyGiflib]],
['imagepipeline', [copyLibjpeg, copyLibpng, copyLibwebp]],
['memchunk', []],
['webpimage', [copyLibwebp]]]
buildToolsVersion "21.1.2"
compileSdkVersion 21
sourceSets {
main {
jni.srcDirs = []
jniLibs.srcDirs = ndkLibs.collect { "$buildDir/${it[0]}" }
}
}
ndkLibs.each { lib -> makeNdkTasks lib[0], lib[1] }
}
task sourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
classifier = 'sources'
}
artifacts.add('archives', sourcesJar)
You don't have ndk-build in the path.
Have you configured the android-ndk properly?
Try adding it and that problem should be solved

How to define apk output directory when using gradle?

How to define apk output directory when using gradle?
I would like to have possibility to upload apk to shared folder after each build.
thats work for me:
android.applicationVariants.all { variant ->
def outputName = // filename
variant.outputFile = file(path_to_filename)
}
or for Gradle 2.2.1+
android {
applicationVariants.all { variant ->
variant.outputs.each { output ->
output.outputFile = new File(path_to_filename, output.outputFile.name)
}
}
}
but "clean" task will not drop that apk, so you should extend clean task as below:
task cleanExtra(type: Delete) {
delete outputPathName
}
clean.dependsOn(cleanExtra)
full sample:
apply plugin: 'android'
def outputPathName = "D:\\some.apk"
android {
compileSdkVersion 19
buildToolsVersion "19.0.3"
defaultConfig {
minSdkVersion 8
targetSdkVersion 19
versionCode 1
versionName "1.0"
}
buildTypes {
release {
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
applicationVariants.all { variant ->
variant.outputFile = file(outputPathName)
}
}
dependencies {
compile 'com.android.support:appcompat-v7:19.+'
compile fileTree(dir: 'libs', include: ['*.jar'])
}
task cleanExtra(type: Delete) {
delete outputPathName
}
clean.dependsOn(cleanExtra)
I found the solution that works with the latest Gradle plugin:
def archiveBuildTypes = ["release", "debug"];
applicationVariants.all { variant ->
variant.outputs.each { output ->
if (variant.buildType.name in archiveBuildTypes) {
// Update output filename
if (variant.versionName != null) {
String name = "MY_APP-${variant.versionName}-${output.baseName}.apk"
output.outputFile = new File(output.outputFile.parent, name)
}
// Move output into DIST_DIRECTORY
def taskSuffix = variant.name.capitalize()
def assembleTaskName = "assemble${taskSuffix}"
if (tasks.findByName(assembleTaskName)) {
def copyAPKTask = tasks.create(name: "archive${taskSuffix}", type: org.gradle.api.tasks.Copy) {
description "Archive/copy APK and mappings.txt to a versioned folder."
print "Copying APK&mappings.txt from: ${buildDir}\n"
from("${buildDir}") {
include "**/mapping/${variant.buildType.name}/mapping.txt"
include "**/apk/${output.outputFile.name}"
}
into DIST_DIRECTORY
eachFile { file ->
file.path = file.name // so we have a "flat" copy
}
includeEmptyDirs = false
}
tasks[assembleTaskName].finalizedBy = [copyAPKTask]
}
}
}
}
For Gradle version 2.2.1 +, you can do this:
def outputPathName = "app/app-release.apk"
applicationVariants.all { variant ->
variant.outputs.each { output ->
output.outputFile = new File(outputPathName)
}
}
This solution is work for classpath 'com.android.tools.build:gradle:3.1.2' and distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip. Put the following code inside your android scope of app-level build.gradle file. When you use command ./gradlew assembleDebug or ./gradlew assembleRelease, the output folder will be copied to the distFolder.
// Change all of these based on your requirements
def archiveBuildTypes = ["release", "debug"];
def distFolder = "/Users/me/Shared Folder(Personal)/MyApplication/apk/"
def appName = "MyApplication"
applicationVariants.all { variant ->
variant.outputs.all { output ->
if (variant.buildType.name in archiveBuildTypes) {
// Update output filename
if (variant.versionName != null) {
String name = "$appName-${variant.versionName}-${output.baseName}.apk"
outputFileName = new File(name)
}
def taskSuffix = variant.name.capitalize()
def assembleTaskName = "assemble${taskSuffix}"
if (tasks.findByName(assembleTaskName)) {
def copyAPKFolderTask = tasks.create(name: "archive${taskSuffix}", type: org.gradle.api.tasks.Copy) {
description "Archive/copy APK folder to a shared folder."
def sourceFolder = "$buildDir/outputs/apk/${output.baseName.replace("-", "/")}"
def destinationFolder = "$distFolder${output.baseName.replace("-", "/")}"
print "Copying APK folder from: $sourceFolder into $destinationFolder\n"
from(sourceFolder)
into destinationFolder
eachFile { file ->
file.path = file.name // so we have a "flat" copy
}
includeEmptyDirs = false
}
tasks[assembleTaskName].finalizedBy = [copyAPKFolderTask]
}
}
}
}

Resources