前言~ 现在使用 Android Studio 开发 Android 已经是大势所趋了,简单的一行代码就可以导入远程库或是本地库,极大简化了开发工作,但仅仅知道如何导入是不行的,为了实际体验一下如何使用 Gradle 发布 library 的过程,将自己的一个自定义View库 TagCornerImageView 发布到了远程仓库,期间遇到了一些不大不小的问题的,特此记录一下~
本文首次发布于2016.4.30日,于2018.9.8日更新。 此种方式已经不再适用,最新方式可以在 Bintray 的提供上传插件的 github 主页 上查看最新方式,但这种方式有点麻烦,确切的说的是很麻烦,所以我们可以使用另一个帮我们封装了这些操作的一个三方库 bintray-release 来便捷的上传库至 bintray。
准备工作 因为我们要将库发布到 Jcenter,而 Jcenter 是由 JFrog Bintray提供的一个 Java 仓库,是目前最大的 Java 和 Android 开源软件构件仓库,上传之前需要在Bintray 官网 申请账号。
新建library 在 Studio 中新建一个 TagCornerImageView 的 Project,其中 app Module可以作为裤子的 demo,新建一个 Module,选择 Android library,然后在demo里面通过 compile project(':yourlibraryname')
引用自己的library。
修改gradle配置 这里我们主要是要用到 Bintray 提供的 gradle 插件来将库上传到远程仓库, 打开根目录下的 build.gradle
文件,修改 dependencies,添加
1 2 classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.0' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3'
更改后 build.gradle
文件为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 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 文件,修改后为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 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 添加:
1 2 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了,例如:
1 compile 'me.wavever.tagcornerimageview:library:0.2.0'
遇到的问题 我们引用一个库时,依赖格式一般为:
1 2 3 4 5 dependencies { ... compile 'org.greenrobot:eventbus:3.0.0' } }
即 compile 'groupId:artifactId:version'
,其中 artifactId 为你的library的名字,就是生成的aar的名字。 Add to Jcente时,出现错误:
Please fix the following before submitting a JCenter inclusion request:- Unable to find a valid POM file in the latest version of your package.
看字义是没有有效的 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