Gradle copy task not copying the files - android

Can someone tell me why my copy task is not working, i have seen some similar questions here but none of them provided a soultion...
def outputJar = "${buildDir}/intermediates/jar"
// Define some tasks which are used in the build process
task copyCompiledClasses(type: Copy, dependsOn: 'assemble') {
// get directory for current namespace
println "Copy compiled classes..."
mkdir Paths.get(outputJar,'classes')
mkdir Paths.get(outputJar,'bin')
from fileTree(dir: 'build/intermediates/javac/debug/classes/', exclude : '**/BuildConfig.class')
into outputJar+'/classes'
}
there are classes in the source folders, and my target folders are being created but the actual copying is not taking place!!!! grrrrr!

Think that the source-spec was wrongful.
task copyCompiledClasses(type: Copy, dependsOn: assemble) {
def outputDir = "${buildDir}/intermediates/jar"
mkdir "${outputDir}/classes"
mkdir "${outputDir}/bin"
from fileTree("${buildDir}/intermediates/javac/debug/classes") {
include '**/*'
exclude '**/BuildConfig.class'
}
into "${outputDir}/classes"
}

Related

Unable to get transitive dependencies of my library in my Android app

I created an Android Library in Android studio, which has some external dependencies(Retrofit, for example).
But when i tried to use this Library in an Android app, The app doesn't include the transitive dependencies(the ones included in the library).
I've already tried publishing the library to Bintray, change the 'implementation' keyword in app-gradle file to 'api'.
I've also tried setting transitive = true in my app's gradle file
When trying to build the Android app, It shows Resource Linking Failed for CardView which's used in my Library.
I faced the same problem while building a Library for Android.
I was trying to directly upload the .aar file from the android studio to the bintray. But appparantly, it was not including the pom.xml file.
So I followed this tutorial to generate the zip file.
Then create a new version at bintray and then manually upload the zip file using the UI upload option
Also, do not forget to check the explode this Archive option while uploading.
Your can then, publish the library and use it with all its transitive dependencies.
Here's an example build.gradle code:
def version = 'your.version'
def localReleaseDest = "${buildDir}/release/${version}"
uploadArchives {
repositories.mavenDeployer {
pom.groupId = 'your.package.name'
pom.artifactId = 'yourModuleName'
pom.version = 'your.version'
// Add other pom properties here if you want (developer details / licenses)
repository(url: "file://${localReleaseDest}")
}
}
task androidJavadocs(type: Javadoc) {
source = android.sourceSets.main.java.srcDirs
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
}
task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
classifier = 'javadoc'
from androidJavadocs.destinationDir
}
task androidSourcesJar(type: Jar) {
classifier = 'sources'
from android.sourceSets.main.java.srcDirs
}
artifacts {
archives androidSourcesJar
archives androidJavadocsJar
}
task zipRelease(type: Zip) {
from localReleaseDest
destinationDir buildDir
archiveName "release-${version}.zip"
}
task generateRelease {
doLast {
println "Release ${version} can be found at ${localReleaseDest}/"
println "Release ${version} zipped can be found ${buildDir}/release-${version}.zip"
}
}
generateRelease.dependsOn(uploadArchives)
generateRelease.dependsOn(zipRelease)
put this code outside all blocks in your app level gradle after modifying it as needed.
Now, sync project and open terminal inside the Android studio, and execute this command:
./gradlew clean build generateRelease
this will generate a .zip file in your app/build directory which you can upload to bintray like described above

Obfuscated interface parameter names in gradle library

I have made a library with some interfaces (HybridMediaPlayer on github). When I import it from gradle in new project and use those interfaces I get changed parameter names such as:
player.setOnPositionDiscontinuityListener(new ExoMediaPlayer.OnPositionDiscontinuityListener() {
#Override
public void onPositionDiscontinuity(int i, int i1) {
}
});
Where the "i" is "reason" and "i1" is "currentWindowIndex".
Why it is changed in other project and how to fix that? Proguard is disabled.
I think this is because on the Maven repo only a Android Archive Library (AAR) exists and no source jar. The AAR only contains the compiled classes and in compiled classes the full variable name is not known anymore. So when your IDE implements the method it doesn't know the names anymore so it defaults to standard naming based on argument types (hence the i for integer).
If you want the correct variable names you should publish a source jar of your project as well to the Jitpack repo. This answer might provide a way to also publish a source jar next to the AAR. When a source jar is also published an IDE will use Gradle to also pull the source jar into the project and will use this when implementing methods to get argument names and such.
The solution for jitpack was adding javadoc for interfaces and this in lib gradle build file:
// build a jar with source files
task sourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
classifier = 'sources'
}
task javadoc(type: Javadoc) {
failOnError false
source = android.sourceSets.main.java.sourceFiles
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
classpath += configurations.compile
}
// build a jar with javadoc
task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
}
artifacts {
archives sourcesJar
archives javadocJar
}
There are two reasons why this could happen:
1. You haven't included any documentation as artifact in your AAR
If this the case then you need to add following tasks in AAR's build.gradle as follows:
task javadoc(type: Javadoc) {
description "Generates Javadoc for ${archivesBaseName}-${version} API"
group JavaBasePlugin.DOCUMENTATION_GROUP
title = "${archivesBaseName}-${version} API References"
source android.sourceSets.main.java.srcDirs, configurations.doc.collect { zipTree(it) }
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
options {
memberLevel = JavadocMemberLevel.PUBLIC
linksOffline('http://developer.android.com/reference/', "${android.sdkDirectory}/docs/reference");
}
include '<path of your public api>/*.java'
exclude '**/BuildConfig.java'
exclude '**/R.java'
exclude '**/test/**/*.java'
failOnError false
}
task androidJavadocsJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
}
artifacts {
archives androidJavadocsJar
}
2. You have already done step 1
If this is the case you need to inform android studio to download the javaDoc. Place following code in your target app's main build.gradle
apply plugin: 'idea'
...
idea {
module {
downloadJavadoc = true
downloadSources = true
}
}
Alternatively, you can follow this SO to do it through android studio.
Note: You need to properly document the Javadoc download in User guide of your AAR so that user of your AAR knows how to overcome the impediment

How to run .cmd file as task in Gradle?

I have .cmd file that I want to include everytime build.gradle is run by Android Studio.
Let's say the filename is create-artifacts.cmd and so in my module's build.gradle.
android {
...
task createArtifacts(type:Exec) {
commandLine = ["create-artifacts.cmd"]
workingDir = file("$rootDir")
}
}
How may I be helped with this?
See the ExecTask documentation
task createArtifacts(type:Exec) {
commandLine 'cmd', '/c', 'create-artifacts.cmd'
workingDir rootDir
}

Android Studio: exclude gradle task from build

I wrote a small task, which updates an Android library from the web. This should only be done on request. I know, that there is a '-x' option, but this seems to apply only on gradle itself. The task gets executed whenever I try to build my project with Android Studio. Is there a way to exclude specific task from being executed?
My gradle task look like:
task downloadSDK {
print 'Downloading SDK...'
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
ant.get(
src: 'http://example.com/SDK.zip',
username:properties.getProperty('USERNAME', null),
password:properties.getProperty('PASSWORD', null),
dest:"${buildDir}/sdk.zip",
verbose:true)
println 'done'
}
task updateSDK(type: Copy) {
print 'Copying SDK...'
delete "src/main/java/"
def zipFile = file("${buildDir}/sdk.zip")
def outputDir = file("src/main/java")
from zipTree(zipFile)
into outputDir
println 'done'
}
updateSDK.dependsOn downloadSDK
I thought that I just have to add << to my updateSDK, but it doesn't seem to work with the Copy task.
Reading the gradle spec more deeply, I found out, that Copy is actually not a task but rather a function. So, my gradle task has to look like:
task updateSDK << {
print 'Copying SDK...'
delete "src/main/java/"
def zipFile = file("${buildDir}/sdk.zip")
def outputDir = file("src/main/java")
copy {
from zipTree(zipFile)
into outputDir
}
println 'done'
}
The difference is that I call the copy function inside a task so that doLast will work correctly.

Aggregate Javadoc for Android project with multiple library modules

I've gone through almost entire Internet in search of a way how to aggregate Javadocs in the project consisting of separate library modules into single Javadoc.
There is a plugin that apparently allows to do that:
https://github.com/nebula-plugins/gradle-aggregate-javadocs-plugin
However, if I run the command specified by the plugin Gradle finds the task and executes it but no output directory is generated.
Any help how to build single Javadoc from multiple modules much appreciated.
I managed to get it working some time ago, apologies for a late response. The solution for aggregatable Javadoc creation is the following:
In each of the subprojects maintained within the project create a task generating the Javadoc:
android.libraryVariants.all { variant ->
task("generate${variant.name.capitalize()}Javadoc", type: Javadoc) {
destinationDir = project.file("$project.projectDir/javadoc/$project.PROJECT_NAME") //Project name in the Project's gradle.properties
title = "A title of my project - $project.PROJECT_VERSION_NAME" //Project version name in the Project's gradle.properties
description "Generates Javadoc for $variant.name."
source = variant.javaCompile.source
ext.androidJar ="${android.sdkDirectory}/platforms/${android.compileSdkVersion}/android.jar"
classpath = files(variant.javaCompile.classpath.files) + files(ext.androidJar) + project.files(android.getBootClasspath().join(File.pathSeparator))
options {
memberLevel = org.gradle.external.javadoc.JavadocMemberLevel.PUBLIC //change the modifier according to your needs
links "http://docs.oracle.com/javase/8/docs/api/"
linksOffline "http://d.android.com/reference", "${android.sdkDirectory}/docs/reference"
}
exclude '**/BuildConfig.java'
exclude '**/R.java'
}
task("bundle${variant.name.capitalize()}Javadoc", type: Jar) {
baseName = "Compass API - ($version)"
description "Bundles Javadoc into zip for $variant.name."
classifier = "javadoc"
from tasks["generate${variant.name.capitalize()}Javadoc"]
}
}
The configuration above adds a Javadoc generation task for each buildVariant of your subproject. At this point you can you can generate Javadoc for each module separately by typing
gradle :myRootProject:mySubproject:generateDebugJavadoc
gradle :myRootProject:mySubproject:generateReleaseJavadoc
gradle :myRootProject:mySubproject:generateMyFancyFlavourDebugJavadoc
gradle :myRootProject:mySubproject:generateMyFancyFlavourReleaseJavadoc
If you use JRE 8 the following configuration disables errors raised by doclint during the Javadoc build (explanation in greater detail here)
if (JavaVersion.current().isJava8Compatible()) {
tasks.withType(Javadoc) {
// disable the crazy super-strict doclint tool in Java 8
//noinspection SpellCheckingInspection
options.addStringOption('Xdoclint:none', '-quiet')
}
}
To aggregate Javadocs of each submodules into a single one create a Plugin in to build.gradle which will add a task to the submodule a partial Javadoc generation of which you are interested in:
class JavadocAggregationPlugin implements Plugin<Project> {
static final String AGGREGATE_JAVADOCS_TASK_NAME = 'aggregateJavadocs'
#Override
void apply(Project project) {
Project rootProject = project.rootProject
rootProject.gradle.projectsEvaluated {
Set<Project> librarySubprojects = getLibraryProjects(rootProject)
if (!librarySubprojects.isEmpty()) {
rootProject.task(AGGREGATE_JAVADOCS_TASK_NAME, type: Javadoc) {
description = 'Aggregates Javadoc API documentation of all subprojects.'
group = JavaBasePlugin.DOCUMENTATION_GROUP
dependsOn librarySubprojects.generateReleaseJavadoc //please note that generateReleaseJavadoc is the name of the separate Javadoc generation task in each library module
source librarySubprojects.generateReleaseJavadoc.source
destinationDir rootProject.file("$rootProject.buildDir/docs/javadoc") //Javadoc destination directory
classpath = rootProject.files(librarySubprojects.generateReleaseJavadoc.classpath)
}
}
}
}
private Set<Project> getLibraryProjects(Project rootProject) {
rootProject.subprojects.findAll { subproject -> subproject.plugins.findPlugin("com.android.library") } //In this case every library module is selected
}
}
Finally, include your plugin to the gradle configuration in the Project's build.gradle below your plugin definition.
apply plugin: JavadocAggregationPlugin
By doing this and rebuilding gradle's configuration you should be able to create aggregated Javadoc in specified directory by typing the following command via cli:
gradle aggregateJavadocs
Hope that helps somehow.
Helpful link: Android Gradle DSL

Categories

Resources