Android 库 Gradle 发布 JAR

Posted

技术标签:

【中文标题】Android 库 Gradle 发布 JAR【英文标题】:Android Library Gradle release JAR 【发布时间】:2013-10-18 21:30:47 【问题描述】:

如何发布android-library项目的Jar打包? 我发现,classes.jar 位于 build/bundles/release/classes.jar 下,我想这是正确的 Jar 包(包含 *.class 文件)。

是否有一些官方方式,将库作为​​ JAR 而不是 AAR 发布?

编辑 我使用 Gradle 发布 Maven 工件,我想发布 JAR 和 AAR 包。所以带有签名的 JAR、md5、清单、... 基于https://chris.banes.me/2013/08/27/pushing-aars-to-maven-central/

apply plugin: 'maven'
apply plugin: 'signing'

configurations 
    archives 
        extendsFrom configurations.default
    


def sonatypeRepositoryUrl
if (isReleaseBuild()) 
    println 'RELEASE BUILD'
    sonatypeRepositoryUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
 else 
    println 'DEBUG BUILD'
    sonatypeRepositoryUrl = "https://oss.sonatype.org/content/repositories/snapshots/"


if(!hasProperty('nexusPassword')) 
    ext.set('nexusPassword', System.console().readPassword("\n\$ Type in password for Sonatype nexus account " + nexusUsername + ": "))


if(!signing.hasProperty('password')) 
    ext.set('signing.password', System.console().readPassword("\n\$ Type in GPG key password: "))


afterEvaluate  project ->
    uploadArchives 
        repositories 
            mavenDeployer 
                beforeDeployment  MavenDeployment deployment -> signing.signPom(deployment) 

                pom.artifactId = POM_ARTIFACT_ID

                repository(url: sonatypeRepositoryUrl) 
                    authentication(userName: nexusUsername, password: nexusPassword)
                

                pom.project 
                    name POM_NAME
                    packaging POM_PACKAGING
                    description POM_DESCRIPTION
                    url POM_URL

                    scm 
                        url POM_SCM_URL
                        connection POM_SCM_CONNECTION
                        developerConnection POM_SCM_DEV_CONNECTION
                    

                    licenses 
                        license 
                            name POM_LICENCE_NAME
                            url POM_LICENCE_URL
                            distribution POM_LICENCE_DIST
                        
                    

                    developers 
                        developer 
                            id "loopj"
                            name "James Smith"
                        
                        developer 
                            id "smarek"
                            name "Marek Sebera"
                        
                    
                
            
        
    

    signing 
        required  isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") 
        sign configurations.archives
    

    task androidJavadocs(type: Javadoc) 
        source = android.sourceSets.main.java.srcDirs
    

    task androidJavadocsJar(type: Jar) 
        classifier = 'javadoc'
        from androidJavadocs.destinationDir
    

    task androidSourcesJar(type: Jar) 
        classifier = 'sources'
        from android.sourceSets.main.java.srcDirs
    

    artifacts 
        archives androidSourcesJar
        archives androidJavadocsJar
    

使用

task androidJar(type: Jar) 
    from android.sourceSets.main.java.srcDirs

将只打包 java 文件,不编译和链接到 android sdk

【问题讨论】:

【参考方案1】:

虽然我没有尝试将带有部署的工件上传到 Sonatype(甚至是本地存储库),但这是我在尝试解决相同问题时设法提出的 a few weeks ago。

android.libraryVariants.all  variant ->
  def name = variant.buildType.name
  if (name.equals(com.android.builder.core.BuilderConstants.DEBUG)) 
    return; // Skip debug builds.
  
  def task = project.tasks.create "jar$name.capitalize()", Jar
  task.dependsOn variant.javaCompile
  task.from variant.javaCompile.destinationDir
  artifacts.add('archives', task);

然后运行以下命令:

./gradlew jarRelease

【讨论】:

恐怕这是正确答案 :-) 谢谢,我会发布我所做的最终编辑以使其正常工作 我也可以确认这行得通。请注意,运行 gradle tasks 时不会显示生成的任务,只有 gradle tasks --all 才会显示。再次感谢! 感谢这确实有帮助,但它仍然不会为依赖项生成类文件。我正在尝试制作一个 SDK jar,基本上它将是一个单独的 jar,但是这个编译不包括它所依赖的模块项目,也不会从依赖部分等中拉下 jars。你有任何完成此任务的建议也将库项目编译到 jar 中,因此我不必分发 4 个 jar,每个库项目一个。那么最好弄清楚如何像 Gson 或 Otto 一样包含 maven 依赖 jar。 有人能指出我如何在这个配置中使用 proguard 吗?似乎用 proguard 定义 buildTypes 不适用。 @Kevin,我将"jar$name.capitalize()" 部分与"jar$variant.name.capitalize()" 交换,以使任务也成为风味名称(variant.name 由 buildType 名称和 productFlavor 名称组成)【参考方案2】:

另外一种通过gradle从库项目生成jar的方式如下:

在你的库的 build.gradle 中:

def jarName = 'someJarName.jar'

task clearJar(type: Delete) 
    delete "$project.buildDir/libs/" + jarName


task makeJar(type: Copy) 
    from("$project.buildDir/intermediates/bundles/release/")
    into("$project.buildDir/libs/")
    include('classes.jar')
    rename('classes.jar', jarName)


makeJar.dependsOn(clearJar, build)

我们在这里所做的只是复制由 Android Gradle 插件生成的 classes.jar。请务必查看此文件的构建目录并查看其内容是否符合您的要求。

然后运行makeJar任务,生成的jar会在library/build/libs/$jarName.jar中

将有根据您的配置发布的类文件。如果你在混淆它,那么 jar 中的文件将被混淆。

【讨论】:

【参考方案3】:

仅仅因为之前的答案不符合我的需求,我分享了我的棘手版本,以生成包含项目类和 aar/jar 依赖项的 jar。

// A tricky jar operation, we want to generate a jar files that contains only the required classes used.
// Dependencies are in jar and aar, so we need to open the aar to extract the classes and put all at the same level
// (aar is a zip that contains classes.jar, the latter is a zip that contains .class files)
task jar(type: Jar) 
    from 
        List<File> allFiles = new ArrayList<>();
        configurations.compile.collect 
            for (File f : zipTree(it).getFiles()) 
                if (f.getName().equals("classes.jar")) 
                    allFiles.addAll(zipTree(f).getAt("asFileTrees").get(0).getDir())
                
            
        
        allFiles.add(new File('build/intermediates/classes/release'))
        allFiles // To return the result inside a lambda
    
    archiveName( project.ext.appName + '.jar' )

这不管理构建类型/风格,但可以进行调整(可以在没有风格的构建类型版本上构建)。

如果您有更聪明或更优雅的解决方案,请分享!

【讨论】:

以上是关于Android 库 Gradle 发布 JAR的主要内容,如果未能解决你的问题,请参考以下文章

如何发布带有远程依赖项 (gradle) 的 Android 库 (aar)?

使用 Gradle 的外部 Android 库项目

如何使用 Gradle 替换 Android Volley 库?

如何使用 Android Studio 和 gradle 构建一个 android 库?

如何在 android 库 gradle 项目中包含依赖项?

在 Gradle 中为 Android 中的库项目构建变体