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
Related
I need to publish my android library (aar) using Gradle to Maven local repo.
But the publication script needs to also generate the Javadocs, while ONLY including Public and Protected methods and classes.
Can't seem to find any information online, especially about the Javadocs part...
Help, I never published a library before.
Ok, after much research I found a solution, so I'm going to share it here if anyone will need this. (I don't want you to be frustrated like I was).
1) Create an android library as a new module inside your project.
2) Inside the build gradle of your library place this code:
plugins {
id 'com.android.library'
id 'maven-publish'
}
android {
nothing special here...
}
This is the code for creating the Javadocs(still inside build.gradle):
task androidJavadocs(type: Javadoc){
source = android.sourceSets.main.java.srcDirs
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
android.libraryVariants.all{ variant->
if (variant.name == 'release'){
owner.classpath += variant.javaCompileProvider.get().classpath
}
}
// excluding a specific class from being documented
exclude '**/NameOfClassToExclude.java'
title = null
options{
doclet = "com.google.doclava.Doclava"
docletpath = [file("libs/doclava-1.0.6.jar")]
noTimestamp = false
// show only Protected & Public
memberLevel = JavadocMemberLevel.PROTECTED
}
}
task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs){
archiveClassifier.set('javadoc')
from androidJavadocs.destinationDir
}
task androidSourcesJar(type: Jar){
archiveClassifier.set('sources')
from android.sourceSets.main.java.srcDirs
}
This is to publish the library to MavenLocal(still inside build.gradle):
afterEvaluate {
publishing{
publications{
release(MavenPublication){
groupId = "com.example.mylibrary"
artifactId = "mycoollibrary"
version = "1.0"
// Applies the component for the release build variant
from components.release
// Adds javadocs and sources as separate jars.
artifact androidSourcesJar
artifact androidJavadocsJar
}
}
}
}
Your default dependencies block:
dependencies {
your dependencies...
}
3) Now you can download the doclava doclet:
Extract the zip, copy the doclava-1.0.6.jar and paste it into your LibraryName/libs folder (can be found using the project view).
You only need doclava if you want to be able to use #hide.
With this annotation, you can exclude specific methods from your Javadocs.
4) Build and publish your library:
Find the gradle tab at the top right side of android studio, or find it from the toolbar View->Tool Windows->Gradle.
Now find your library -> tasks -> publishing -> publishReleasePublicationToMavenLocal.
5) To consume the library from another project:
Go to the settings.gradle file (of the consuming project) and add MavenLocal() as the first repository in the the dependencyResolutionManagement block.
And inside the module build gradle add your library as a dependency:
dependencies{
implementation 'com.example.mylibrary:mycoollibrary:1.0'
}
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
Gradle/maven newbie here. I have created a library that is currently published to bintray/jcenter as an AAR, to be used with gradle in Android Studio projects.
However, since my library doesn't really have any hard Android dependencies, and may be used in any Java SE environment, I would like to publish it also as a normal jar. Since I am not very familiar with the non-android java development community I am not sure if this means I should publish it to Maven central, or would developers typically be fine fetching my library from bintray, given that the library is actually hosted in a maven repo on bintray?
Should I simply extend my artifacts to include the jar (alongside with the aar, the javadoc and the source jar), or should I typically publish the jar separately, say to Maven central?
Getting the bintray/jcenter stuff up and running was no picnic, I found a few guides on how to do it, but none was really complete, but finally I have it working. I am however having a surprisingly difficult time finding a similar easy guide for maven publishing.
My gradle file looks like this:
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
apply plugin: 'com.jfrog.bintray'
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {
minSdkVersion 1
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
}
}
group = <my library name>
version = <my version>
dependencies {
}
task sourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
classifier = 'sources'
}
task javadoc(type: Javadoc) {
source = android.sourceSets.main.java.srcDirs
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
options.overview = 'src/main/overview.html'
}
task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
}
artifacts {
archives javadocJar
archives sourcesJar
}
bintray {
user = properties.getProperty("bintray.user")
key = properties.getProperty("bintray.apikey")
configurations = ['archives']
pkg {
repo = "maven"
name = <my library name>
websiteUrl = <my site url>
vcsUrl = <my git url>
licenses = ["Apache-2.0"]
publish = true
}
}
The com.github.dcendents.android-maven plugin offers an install task that produces the AAR, Source Jar and Javadoc Jar. I have defined my own bintray task that publishes the library to bintray. What would be the easiest way to create a task for publishing my library also as a standard jar to maven? Can I use com.github.dcendents.android-maven for this as well, or do I need a separate plugin?
I have a library project, libParent, that includes another library project, libChild, as a dependency. If you look at the build.gradle dependencies section, you will see something like the following:
dependencies {
...
compile project(':libChild')
}
Now, I want to publish libParent to maven as an aar file. Note that libChild has not been published, but I would like to include its sources/resources within libParent's artificat. The maven publishing section of my build.gradle file looks like the following:
task sourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
classifier = 'sources'
}
task javadoc(type: Javadoc) {
source = android.sourceSets.main.java.srcDirs
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
}
task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
}
artifacts {
archives javadocJar
archives sourcesJar
}
Once I publish my module and include it as a dependency in my app, I get the following error:
Could not find 'libParent:libChild:unspecified'
Searched in the following locations:
https://oss.sonatype.org/content/respositories/snapshots/libParent/libChild/unspecified/libChild-unspecified.pom
I know that libChild is not getting baked into my published artifact, but how do I go about making sure that the sources/resources of libChild get included?
You can't do it.
If a library has a dependency, the pom file of the parent lib will contain this dependency.
You can't resolve this dependency including the sources/resources.
You have to publish also the child lib.
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