Android Studio 中提交 library 到 Jcenter 及遇到的坑

2,263 阅读4分钟
原文链接: www.jianshu.com

前言~

现在使用Android Studio开发Android已经是大势所趋了,简单的一行代码就可以导入第三方库,极大方便了开发的流程,但仅仅知道如何导入是不行的,最近自己也尝试这开源了一个还不完善的裤子,其实主要是体验一下使用Gradle发布library的过程,还是遇到了一些不大不小的问题的,所以说仅仅看是没有多大用的,很多事情还是要自己尝试才有很深的体会的。

准备工作

因为我们要将裤子发布到Jcenter,而Jcenter是由JFrog公司提供的Bintray中的Java仓库,是目前最大的Java和Android开源软件构件仓库。所以我们需要先申请一个账号:Bintray官网,但尴尬的是,这个网站需要科学上网,所以非戦闘員の迅速な避難をしてください。。但不知道为什么,有时候翻了还是会上不去,类似下图。


WTF


额,扯多了,注册好后需要记住用户名和apikey(个人设置界面),后面发布的时候要用到,下面就以自己的这个裤子为例记录一下。

新建library

在Studio中新建一个TagCornerImageView的Project,其中app Module可以作为裤子的demo,新建一个Module,选择Android library,然后在demo里面通过compile project(':yourlibraryname')引用自己的library。

修改gradle配置

打开根目录下的build.gradle文件,修改dependencies,添加

classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.0'
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3'

更改后build.gradle文件为:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.5.0'
        classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.0'
        classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

注意:这里的maven-gradle-plugin版本为1.3,如果为1.2会出错。
打开library下的build.gradle文件,修改后为:

apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
apply plugin: 'com.jfrog.bintray'
version = "0.2.0"    //版本号,以后每次更新library都得更改
android {

    compileSdkVersion 23
    buildToolsVersion "23.0.3"
    resourcePrefix "wavever_"  //资源前缀

    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 23
        versionCode 1
        versionName version
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    lintOptions {
        abortOnError false
    }

}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:23.3.0'
}

def siteUrl = 'https://github.com/wavever/TagCornerImageView'    //Homepage URL of the library
def gitUrl = 'https://github.com/wavever/TagCornerImageView.git'    //Git repository url
def issueUrl = 'https://github.com/wavever/TagCornerImageView/issues'    //issue url of the library
group = "me.wavever.tagcornerimageview"    //
install {
    repositories.mavenInstaller {
        // This generates POM.xml with proper parameters
        pom {
            project {
                packaging 'aar'
                // Add your description here
                name 'A custom imageview that can add different style tag on corner'
                url siteUrl
                // Set your license
                licenses {
                    license {
                        name 'The Apache Software License, Version 2.0'
                        url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
                    }
                }
                developers {
                    developer {
                        id 'wavever' //your user ID
                        name 'wavever' //your name
                        email 'wavever.ht@gmail.com' //your email
                    }
                }
                scm {
                    connection gitUrl
                    developerConnection gitUrl
                    url siteUrl
                }
            }
        }
    }
}
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
}
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
bintray {
    user = properties.getProperty("bintray.user")
    key = properties.getProperty("bintray.apikey")
    configurations = ['archives']
    pkg {
        repo = "maven"    //发布到Bintray的哪个仓库
        name = "TagCornerImageview"    //发布到Bintray上的名字
        desc = "A library to add tag for ImageView."    //项目描述
        websiteUrl = siteUrl
        vcsUrl = gitUrl
        issueTrackerUrl = issueUrl
        licenses = ["Apache-2.0"]
        labels = ['android']    //标签
        publish = true
        publicDownloadNumbers = true
    }
}

最后要用到的就是前面提到的username和apikey了,在根目录下的local.properties添加:

bintray.user=wavever
bintary.apikey=your bintray apikey

构建&上传

在Studio下的Terminal执行命令:gradlew build ,如果在library\build\outputs\aar生成:library-debug.aar 和 library-release.aar 两个aar文件,这就是我们要上传的文件,接着执行:
gradlew bintraryUpload 。上传成功后,就可以在自己的maven仓库看到上传的library了,接着就可以点击右下角的Add to JCenter ,添加成功后,基本隔天会受到许可邮件。



然后就可以引用自己的library了,例如:

compile 'me.wavever.tagcornerimageview:library:0.2.0'

遇到的问题

  • 我们引用一个库时,依赖格式一般为:
    dependencies {
      ...
      compile 'org.greenrobot:eventbus:3.0.0'
      }
    }
    compile 'groupId:artifactId:version',其中 artifactId 为你的library的名字,就是生成的aar的名字。
  • Add to Jcente时,出现错误:

    ERROR

    看字义是没有有效的POM文件,从maven仓库删除后,从新发布了一遍就好了。
  • 看到许多关于此类的博客,在resourcePrefix上都是说可以随便填,如果你没有自定义属性,随便填是可以的,但如果你需要在xml中引用自己自定义的属性,那么你会发现你的library中的attrs.xml会被红色的波浪下划线所标记,并且提示如下:
    Resource named 'TagCornerImageView' does not start with the project's resource prefix 'wavever_'; rename to 'wavever_TagCornerImageView' ? In Gradle projects you can specify a resource prefix that all resources in the project must conform to. This makes it easier to ensure that you don't accidentally combine resources from different libraries, since they all end up in the same shared app namespace.
    当然你也可以忽略这个提示,但是我们还是要想一下为什么会有这个提示,从提示内容可以看出来,使用前缀名,目的是为了区分不同的library,因为他们会共用一个命名空间,类似与,在一个xml文件中,使用
    xmlns:app="http://schemas.android.com/apk/res-auto",然后我们就可以通过app:来使用自定义的属性,但如果一个xml文件中有两个不同的自定义控件,并且都有个共同的自定义属性,那么就会出现歧义,这应该也是一种良好的规范吧。

    参考

    Android Studio发布项目到Jcenter
    Publish Gradle Android Library to jCenter Repository