美文网首页Android开发随笔技术文
Android 项目打包到 JCenter 的坑

Android 项目打包到 JCenter 的坑

作者: TiouLims | 来源:发表于2015-05-14 16:15 被阅读4480次

    搜索下如何发布 Android 项目的信息,大部分都会找到这篇文章 Publishing Gradle Android Library to jCenter Repository,中文的指引可以看使用Gradle发布项目到JCenter仓库。不过,如果按照这些文章提供的 build.gradle,可能还会遇到一些坑。

    调用 getBootClassPath() 出错

    具体的错误信息是

    Cannot call getBootClasspath() before setTargetInfo() is called.
    

    这个是 gradle 的 android plugin 1.1.0 版本的 bug,见 Issue 152811 - android - Android Gradle Plugin 1.1.0 breaks Javadoc tasks。将插件更新到 1.1.1 以上版本就可以了。

    classpath 'com.android.tools.build:gradle:1.1.2'
    

    GBK 编码问题

    Windows 用户可能会遇到这个问题,因为你将文件设置为 UTF-8 编码,javadoc 默认的是系统编码,Windows 就是 GBK 编码。所以一旦 java 文件中出现中文注释就会报错,提示无法映射的GBK编码

    这个很容易解决,为 javadoc 指明编码就可以。在 gradle 可以这么做: options.encoding = "utf-8",具体的任务代码如下:

    task javadoc(type: Javadoc) {
        ...
        options.encoding = "utf-8"
        ...
    }
    

    javadoc 的依赖问题

    task javadoc(type: Javadoc) {
        source = android.sourceSets.main.java.srcDirs
        classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
    }
    

    文章中的 javadoc 任务是这样的,重点在 classpath 那一行,这一行的意思是添加 Android 框架到 javadoc 的 classpath 中。不过,如果你的项目使用了其他第三方依赖,那 javadoc 任务很可能会执行失败的,因为上面的代码并没有这些添加第三方依赖到 classpath 中。比如我的项目,有下面这些依赖:

    dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar'])
        compile 'com.google.code.gson:gson:2.3.1'
        compile 'com.android.support:gridlayout-v7:22.1.1'
        compile 'com.android.support:support-v4:22.1.1'
        compile 'com.android.support:appcompat-v7:22.1.1'
    }
    

    跑起上面的 javadoc 就会报错,类似下面的错误:

        xxxx.java:20: 错误: 找不到符号
        public static <T> T create(JsonElement json, Class<T> classOfModel) {
                                   ^
      符号:   类 JsonElement
      位置: 类 xxxx
    

    这时最简单的方法就是把第三方依赖加入 classpath:

     classpath += project.files(configurations.compile.files,android.getBootClasspath().join(File.pathSeparator))
    

    但是仍然报错

    Error:Could not find com.android.support:gridlayout-v7:22.1.1.
    Searched in the following locations:
    USER_HOME/.m2/repository/com/android/support/gridlayout-v7/22.1.1/gridlayout-v7-22.1.1.pom
    USER_HOME/.m2/repository/com/android/support/gridlayout-v7/22.1.1/gridlayout-v7-22.1.1.jar
    https://jcenter.bintray.com/com/android/support/gridlayout-v7/22.1.1/gridlayout-v7-22.1.1.pom
    https://jcenter.bintray.com/com/android/support/gridlayout-v7/22.1.1/gridlayout-v7-22.1.1.jar
    ...
    

    这时我的 repositories 是这样的:

    allprojects {
        repositories {
            mavenLocal()
            jcenter()
        }
    }
    

    找不到 support 库,因为 support 库是 sdk 下载下来的,所以在这两个位置找不到也很正常。Android Plugin 自带的任务执行起来却不会报错,想必是做了特殊处理。

    sdk 目录下也有个 maven repository,就是那些 support libs 所在的位置。

    ANDROID_HOME\extras\android\m2repository
    

    加进去再试一下

    Properties properties = new Properties()
    properties.load(project.rootProject.file('local.properties').newDataInputStream()) // local.properties 有 sdk 的绝对位置
    allprojects {
        repositories {
            maven {
                url properties.getProperty("sdk.dir")+"/extras/android/m2repository"
            }
            mavenLocal()
            jcenter()
        }
    }
    

    依然报错,这次是找到那些库了,但因为 sdk 目录下的库是 aar 格式的,javadoc 不支持。所以问题到这里近乎无解了,幸好我在 stackoverflow 找到另一个 android 生成 javadoc 的方法。稍加改写就可以生成 javadoc 为 maven 所用:

    android.libraryVariants.all { variant ->
        println variant.javaCompile.classpath.files
        if(variant.name == 'release') { //我们只需 release 的 javadoc
            task("generate${variant.name.capitalize()}Javadoc", type: Javadoc) {
                // title = ''
                // description = ''
                source = variant.javaCompile.source
                classpath = files(variant.javaCompile.classpath.files, project.android.getBootClasspath())
                options {
                    encoding "utf-8"
                    links "http://docs.oracle.com/javase/7/docs/api/"
                    linksOffline "http://d.android.com/reference", "${android.sdkDirectory}/docs/reference"
                }
                exclude '**/BuildConfig.java'
                exclude '**/R.java'
            }
            task("javadoc${variant.name.capitalize()}Jar", type: Jar, dependsOn: "generate${variant.name.capitalize()}Javadoc") {
                classifier = 'javadoc'
                from tasks.getByName("generate${variant.name.capitalize()}Javadoc").destinationDir
            }
            artifacts {
                archives tasks.getByName("javadoc${variant.name.capitalize()}Jar")
            }
        }
    }
    

    以 support-v4 为例,configurations.compilevariant.javaCompile.classpath 打印出来的位置是不同的,分别是

    • SDK_HOME\extras\android\m2repository\com\android\support\support-v4\22.1.1\support-v4-22.1.1.aar
    • PROJECT_HOME/MODULE/build/intermediates/exploded-aar/com.android.support/support-v4/22.1.1/jars/libs/internal_impl-22.1.1.jar

    看来 Android Plugin 确实有特殊处理。生成 javadoc 没问题其他的也基本没有什么问题,最终的 build.gradlegist

    关于 javadoc 的坑写得十分啰嗦,主要是想和大家分享一些 gradle 的使用经验,其实 gradle 并不困难,主要是 Android Plugin 缺乏文档又鲜有例子,所以折腾起来比较难受。Android Plugin 的用户指南是在 New Build System 而 DSL 文档则是在 Android Plug-in for Gradle 右边有个下载 DSL 文档按钮。Gradle 可看官方的用户指南 Gradle User Guide,我还有一个乱糟糟的笔记这个不足为看了。

    如何上传到 JCenter 这个按照一开始提及文章的操作应该是没什么问题的,反正我没遇到问题,成功上传了 lru-image。其实,不用上传到 jcenter 单单运行 install 任务, gradle 会在 maven 的本地仓库中生成工件(artifact),只需将 mavenLocal 添加到 repositories,我们可以像发布到 JCenter 一样引用自己的库,方便打包那些多个项目共享又不想发布的私有库。

    allprojects {
        repositories {
            mavenLocal()
            jcenter()
        }
    }
    

    相关文章

      网友评论

      • Aaron96:android.libraryVariants.all { variant -> ...` 代码块 能不能麻烦告诉我一下这个应该加在哪里,是引入local.properties后面吗?
        TiouLims:@路国强 完整代码参考一下这个 gist: https://gist.github.com/douo/ef1856415c461953d3c1
        路Promenade:同问,加载哪里啊?
      • 思落羽:用了你的gist那个还是不行,按着你发出来的stackoverflow评论下面那条写成功了:
        task javadoc(type: Javadoc) {
        source = android.sourceSets.main.java.srcDirs
        classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
        failOnError false
        }
        fd3662f094ce:@思落羽 failOnError false 就这句,不检测异常情况。
      • 小小流氓:第三方引用库 怎么弄呢?
      • SingorZhu:请问上传到jcenter的是不是不能设置成私有的?
      • mrwangyong:真的帮了我大忙,非常感谢!!
      • 小草房Fang:No value has been specified for property 'packageName' 只有这一个错误, 是什么原因? 好像是install pom出错了.
      • 范二青年_Flyco::library:
        TiouLims:@b3447988bf1d 说的是传递性的问题吗?看一下官方文档应该能找到解答:https://docs.gradle.org/current/userguide/dependency_management.html#sub:exclude_transitive_dependencies
      • 8cc64b155343:感谢~貌似是我电脑上的github证书出问题了,让我朋友帮我打开这个地址就可以把看到了,
      • 8cc64b155343:是的 gist打不开 或许说是我不会使用这种地址
      • 8cc64b155343:你好 根据你的classpath += project.files(configurations.compile.files,android.getBootClasspath().join(File.pathSeparator)) 和本地sdk路径配置好后 别的第三方包都可以找到了 但是还是报错找不到V4包 请问这是什么情况,而且你的build.gradle文件那个地址无法访问
        TiouLims:@米代 gist 打不开吗?
        你用的代码是错误的示范,继续读下去有讨论 support libs 的依赖方法,正确的代码是`android.libraryVariants.all { variant -> ...` 代码块

      本文标题:Android 项目打包到 JCenter 的坑

      本文链接:https://www.haomeiwen.com/subject/yvyqqttx.html