【译】
在Android Studio里,如果你想引入任何library到自己的项目中,只需要很简单的在module的build.gradle文件中添加一行依赖。
dependencies {
compile 'com.inthecheesefactory.thecheeselibrary:fb-like:0.9.3'
}
就是这么简单,library已经可以在自己的项目中使用。
这看起来非常酷,但你也许会好奇Android Studio是从哪里去抓取到这些library的?这篇博客会详细讲解如何发布自己的library,使之能够与全世界的开发者分享,这不仅使得世界更加美好,也让自己看起来更酷。
Android Studio是从哪里去抓取到这些library的?
用这个简单的问题开始,我相信不是所有的人都确切的知道Android Studio是从哪里抓取到这些library的。它是通过Google去搜索,然后下载到我们项目中的么?
好吧,其实并不复杂。Android Studio是从我们定义在build.gradle文件中的Maven资源中心去下载library的。(Apache Maven是Apache为开发者提供的一个发布libraries的文件服务工具)。基本上,现在有两种标准的libraries仓库,分别是jCenter和Maven Central。
jcenter
jcenter是一个托管在bintray.com的资源库。你可以在这里找到需要的资源。
为了能在你的项目中使用jcenter,你需要像下面一样,在自己的build.gradle文件中定义自己的资源库。
allprojects {
repositories {
jcenter()
}
}
Maven Central
Maven Central是一个托管在sonatype.org的资源库。你可以在这里找到需要的资源。
为了能在你的项目中使用Maven Central,你需要像下面一样,在自己的build.gradle文件中定义自己的资源库。
allprojects {
repositories {
mavenCentral()
}
}
请注意,虽然jcenter和Maven Central都是标准android library资源仓库,但他们的托管地址完全不同,它们的内容是由不同提供者提供的,而且之间并没有任何关联。所以也就可能,在jcenter中能够找到的library,在Maven Central和viceversa中并不能找到。
除了这两个标准的资源库外,我们也可以定义特殊的资源库,引入一些开发者托管在自己服务器上的library。Twitter的Fabric.io就完全是托管在自己服务器上的Maven资源库。如果你想要使用任何fabric.io上面的library,都需要向下面一样,定义资源库的url。
repositories {
maven { url 'https://maven.fabric.io/public' }
}
然后你可以通过和下面相似的方法获取该资源库里面的任何library。
dependencies {
compile 'com.crashlytics.sdk.android:crashlytics:2.2.4@aar'
}
但是哪一种方式更好呢,是上传library到标准的服务器上,还是搭建自己的服务器?为了让我们的library能够被大众所使用,建议上传到标准服务器上。其他开发者只需一行代码定义依赖名字而无需其他操作。在这篇博客中,我们只关注jcenter和Maven Central这两种能够给开发者提供更好方式的资源库。
事实上,android stuido还存在除Maven外的另一种类型的资源库,叫做Ivy Repository,但从我个人的经验来看,我还从未见过任何人使用它,所以这篇博客先简单的忽略这种类型。
Understand jcenter and Maven Central
想知道为什么是两个标准资源库而不是一个?
事实上,它们都拥有相同的职责:托管java/Android library。完全由开发者决定把library上传到它们中的一个或两个上。
最开始的时候,Android Studio选择Maven Central作为默认资源库。一旦你从老版本的Android Studio创建了一个新的项目,mavenCentral()会自动定义到build.gradle中。
但是Maven Central存在一个较大的问题,即对开发者并不友好。上传library比较困难。为了能够做到上传,开发者从某种程度上讲得具备极客的能力。再考虑到其他一些原因,比如安全问题,Android Studio团队决定把默认资源库改为jcenter,所以新版Android Studio创建新项目的时候,默认定义jcenter()而不是mavenCentral()。
这里列举了一些他们决定从Maven Central切换jcenter的主要原因:
- jcenter通过CDN传输library,这意味着开发者能够享受更快的加载速度。
- jcenter是世界上最大的java库,所以能在Maven Central里面找到的,基本在jcenter里面也能找到。
- 非常容易上传library到jcenter仓库,没有必要签名或做其他一些在Maven Central上很复杂的操作。
- 界面友好
- 如果你想上传library到Maven仓库,在bintray网站单击即可(一次性设置)。
通过以上的原因以及我自己的经验,我必须说,把jcenter作为默认仓库是非常明智的决定。
所以,这边博客主要关注jcenter,一旦你把library成功上传到jcenter,那么也可以非常方便的再上传到Maven Central。
gradle是如何把library从仓库拉取下来的?
当我们讨论如何把library上传到jcenter之前,我们先讨论下gradle是如何从仓库抓取library的。例如,当我们像下面这样在build.gradle里面定义依赖的时候,library文件是如何下载到你的项目的。
compile 'com.inthecheesefactory.thecheeselibrary:fb-like:0.9.3'
首先我们得了解library字符串的格式,它包含三个部分:
GROUP_ID:ARTIFACT_ID:VERSION
以上面的字符串为例:
GROUP_ID是com.inthecheesefactory.thecheeselibrary,ARTIFACT_ID是fb-like,VERSION是0.9.3
GROUP_ID定义了library的组,很可能不同功能的library存在于同一背景下,如果library在相同的组,那么它们共享相同的GROUP_ID。通常我们用开发者的包名加上library的名字作为GROUP_ID,例如com.squareup.picasso,然后我们再定义真正的library名作为ARTIFACT_ID。关于VERSION,就是版本号,虽然它可以是任意字符,但我建议它设置为x.y.z的格式,如果你愿意,也可以跟上-beta。
这有一些真实的library例子,你会注意到,每一个都很容易辨别出library的名字和包名。
dependencies {
compile 'com.squareup:otto:1.3.7'
compile 'com.squareup.picasso:picasso:2.5.2'
compile 'com.squareup.okhttp:okhttp:2.4.0'
compile 'com.squareup.retrofit:retrofit:1.9.0'
}
像上面一样添加了依赖会发生什么呢?很简单,Gradle会向Maven仓库服务器询问library是否存在,如果存在,则会返回library的下载地址,通常是GROUP_ID/ARTIFACT_ID/VERSION_ID的格式,例如,你可以从http://jcenter.bintray.com/com/squareup/otto/1.3.7和https://oss.sonatype.org/content/repositories/releases/com/squareup/otto/1.3.7/找到com.squareup:otto:1.3.7的library文件。
然后Android Studio会下载这些文件到我们的机器上,再编译到我们的项目中,就是这样,没什么复杂的!
我相信,你已经很清楚的知道,从远程仓库拉下来的,不过是托管在服务器上的jar或arr格式的文件。相对于自己去下载这些文件,单独拷贝编译到自己的项目,这种方式最大的好处是只需要定义一些依赖文本,而不需要其他更多的操作。
了解aar文件格式
等等,我说过这儿有两种形式的library托管在远程仓库里,jar和aar,jar倒是常用的,我相信大家都知道,不过,aar文件又是什么呢?
aar文件是更进一步的jar文件,它被创造出来是因为一些Android Library需要嵌入一些android的特殊文件,比如AndroidManifest.xml, Resources, Assets or JNI等jar文件不包含的内容。所以aar文件被创造出来解决这些问题。一般说来,jar只是有着不同结构的zip文件,jar文件被嵌入在aar文件里,名为class.jar。aar中余下部分如下:
- /AndroidManifest.xml (mandatory)
- /classes.jar (mandatory)
- /res/ (mandatory)
- /R.txt (mandatory)
- /assets/ (optional)
- /libs/*.jar (optional)
- /jni/<abi>/*.so (optional)
- /proguard.txt (optional)
- /lint.jar (optional)
正如你所看见的,aar文件是专门为Android设计的,所以这篇博客将会告诉你如何创建并上传一个aar格式的library。
如何上传你的library到jcenter
到现在,我相信你对远程library仓库的工作模式已经有了基本的了解。现在开始最重要的环节:上传过程。目标很简单,即如何将我们的库文件上传到http://jcenter.bintray.com。一旦我们学会了上传,那么library也就能够被发布了。两个问题需要关注:如果创建aar文件以及如何上传编译好的文件到远程仓库。
虽然它需要很多步骤,但我必须说,这完全不困难,因为bintray已经为我们准备好了一切。你可以通过下面的图了解整个过程。
因为有很多细节,所以我把整个过程分为了7部分,以便能够循序渐进的描述清楚。
Part 1 : 在Bintray上创建一个包
首先,你需要在bintray上创建一个包,为了完成这步,你需要一个bintray账号并且在网站上创建一个包。
第一步:在bintray.com上注册账号。
第二步:注册成功后,登陆网站点击maven。
第三步:点击Add New Package,为你的library创建一个新的包。
第四步:输入必要的信息
虽然如何命名包名没有明确的规则,但有一些约定:所有字符小写,单词间通过“-”号连接,比如,fb-like。
一旦上面每一步都完成了,单击Create Package完成创建。
第五步:网站会自动重定向到编辑页面。点击包名下面的名字可以进入具体的信息页面。
好了,现在你已经在bintray上有了自己的Maven仓库,准备好上传自己的library文件了。
Bintray账号的注册工作已经完成了,接下来将会和Maven Central的提供者,Sonatype打交道。
Part 2 : 为Maven Central创建一个Sonatype账号
提示:如果你没有计划上传library文件到Maven Central,你可以跳过第二部分和第三部分。但无论如何,我建议不要跳过,因为还是有很多的开发者在用这个仓库。
就想jcenter一样,如果你想要上传你的library到Maven Central,你需要在它的提供者,也就是Sonatype网站上注册一个账号。
你所需要知道的是,你必须在Sonatype网站上创建一个JIRA Issue Tracker的账号。为了完成这一步,请到Sonatype Dashboard注册。
一旦你完成注册,你需要请求发布library到Maven Central。虽然这个过程可能没有任何意义(至少对我来说),但你必须在JIRA上创建一个请求,让他们允许你上次你的library到Maven Central。
为了创建一个问题描述,到Sonatype Dashboard网站,通过账号登陆,然后点击顶部的Create按钮。
填入以下的信息:
Project: Community Support - Open Source Project Repository Hosting
Issue Type: New Project
Summary: 你library文件的名称,例如:Cheese Library
Group Id: 填入GROUP_ID的根名称,例如:com.inthecheeselibrary。在你得到批准之后,每个以com.inthecheeselibrary开头的library文件,都会被允许上传的远程仓库,例如:com.inthecheeselibrary.somelib
Project URL: 填入一个你准备用来描述该library的地址,例如:https://github.com/nuuneoi/FBLikeAndroid
SCM URL: 源码管理的地址,例如:https://github.com/nuuneoi/FBLikeAndroid.git
保持没有修改的部分,点击Create。我们要做的结束了,接下来是最难的部分:耐心等待。大概需要一周的时间审核,然后才能在Maven Central中访问自己的library。
最后要做的是,在Bintray Profile的账号选项卡页面,填入Sonatype OSS的用户名。
点击Update,这个部分我们就完成了。
Part 3 : 在Bintray上开启自动签名
正如上面提到的,我们可以通过jcenter上传一个library到Maven Central,但前提是,我们需要对library进行签名。bintray提供一个自动化的工具,允许通过网络接口上传的library能够在上传后自动签名。
第一步是通过命令行,生成一个key。(如果使用的是windows,请在cygwin环境下操作)
gpg --gen-key
这里有一些强制性填充的字段,大部分情况下用默认值就可以,但是对于一些字段,需要填入你自己的信息,比如,你的真实姓名,密码等等。
一旦key被创建,调用下面的命令行,可以看到key的信息。
gpg --list-keys
如果没有出错,信息会像下面一样被展示出来。
pub 2048R/01ABCDEF 2015-03-07
uid Sittiphol Phanvilai <yourmail@email.com>
sub 2048R/98765432 2015-03-07
现在我们需要上传公钥到管理中心使它生效。为了完成这一步,请调用下面的命令行,其中替换PUBLIC_KEY_ID为2048R/后面的8位16进制数,在这个例子中,即为:01ABCDEF。
gpg --keyserver hkp://pool.sks-keyservers.net --send-keys PUBLIC_KEY_ID
接下来,通过以下命令,以ASCII格式导入公钥和私钥,请替换其中的yourmail@email.com为前面你生成key所使用的email。
gpg -a --export yourmail@email.com > public_key_sender.asc
gpg -a --export-secret-key yourmail@email.com > private_key_sender.asc
打开Bintray的Edit Profile页面,点击GPS Signing。填入在前面步骤中导出的public_key_sender.asc和private_key_sender.asc文件里面的公钥和私钥。
点击Update保存key。
最后一步是开启自动签名,到Bintray的主页,点击maven,再点击Edit。
选中GPG Sign uploaed files automatically的勾选框,开启自动签名。
点击Update保存,到现在为止,每一个单独的library上传到Maven仓库都能够被自动签名,而且已经准备好一键发布到Maven Central。
请注意,这是一个一次性行为,将会被应用到以后每一个创建的library中。
Bintray和Maven Central的部分都已经准备好了,现在让我们切换到Android Studio部分。
Part 4 : 准备Android Studio工程项目
在许多情况下,我们可能在一个项目里,需要上传多个library,也可能不需要。所以我建议最好的结构是按照Module来划分,基本上我建议最少有两个Module,一个应用程序的Module,一个包含了你想要上传到远程仓库源码的library的Module。请注意,如果在你的项目里不止包含了一个library,请创建另外一个Module:每一个library对应一个Module。
我相信大家都知道如何创建一个library module,多以我不会太深入的讲这个部分。
接下我们需要把bintray的插件应用到你的项目中。要做到这一点,我们需要像下面这样修改project的build.gradle文件中的依赖部分。
dependencies {
classpath 'com.android.tools.build:gradle:1.2.3'
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.4'
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3'
}
gradle构建工具的版本需要在1.1.2以上,因为之前的版本存在一个严重的bug。在这个例子中,我们选择使用1.2.3版本。
接下来,我们需要修改local.properties,定义用于bintray身份认证的用户名和api密钥,以及密码。
之所以把这些信息放到这个文件中,是因为一些敏感信息,包括版本控制,不应该被共享。幸运的是,自从项目被创建,local.properties文件就已经被添加了.gitignore,所以这些敏感信息不会意外上传到git服务器。
下面是需要添加的配置信息:
bintray.user=YOUR_BINTRAY_USERNAME
bintray.apikey=YOUR_BINTRAY_API_KEY
bintray.gpg.password=YOUR_GPG_PASSWORD
把你在bintray上的用户名写到第一行,把你在Edit Profile网页上,API Key的信息写到第二行。最后一行是你在前面步骤中,用来创建GPG key的密码。最后保存并关掉这个文件。
最后需要修改的文件是module的build.gradle文件。打开它并把下面的信息添加到里面。
apply plugin: 'com.android.library'
ext {
bintrayRepo = 'maven'
bintrayName = 'fb-like'
publishedGroupId = 'com.inthecheesefactory.thecheeselibrary'
libraryName = 'FBLike'
artifact = 'fb-like'
libraryDescription = 'A wrapper for Facebook Native Like Button (LikeView) on Android'
siteUrl = 'https://github.com/nuuneoi/FBLikeAndroid'
gitUrl = 'https://github.com/nuuneoi/FBLikeAndroid.git'
libraryVersion = '0.9.3'
developerId = 'nuuneoi'
developerName = 'Sittiphol Phanvilai'
developerEmail = 'sittiphol@gmail.com'
licenseName = 'The Apache Software License, Version 2.0'
licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
allLicenses = ["Apache-2.0"]
}
保持bintrayRepo为现在这个样子,改变bintrayName为你自己的包名,修改其他配置来匹配你自己的library信息。有了上面的脚本,每个人都可以通过下面一行gradle脚本使用这个library。
compile 'com.inthecheesefactory.thecheeselibrary:fb-like:0.9.3'
最后一步是应用两个脚本,用于创建library文件以及上传构建文件到bintray,在build.gradle文件的最后添加以下脚本即可(为了方便,我直接把这些文件链接到github的服务器上)。
// Place it at the end of the file
apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/installv1.gradle'
apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/bintrayv1.gradle'
现在,你的项目已经设置并且准备好了上传到bintray。
Part 5 : 上传你的library到bintray空间
现在是时候上传你library到你自己的bintray仓库了。首先,请切换到Android Studio的Terminal界面。
第一步是检查代码的正确性,构建library文件(aar,pom,等等)。输入下面的命令。
> gradlew install
如果没有任何错误,将会显示下面的命令行:
BUILD SUCCESSFUL
我们已经完成了一半,接下来需要上传构建文件到bintray,输入下面的命令行:
> gradlew bintrayUpload
如果显示下面这行,那就成功了:
SUCCESSFUL
在bintray网站的界面上检查你的包,你会发现版本区域有了变化。
点击它切换到Files页面,你会看到上传的library文件。
恭喜,现在你的library已经在线上,可以被任何人使用。
但是,到你的library还只在Maven仓库里,而没有在jcenter,所以任何想要使用你的library的人,都必须像下面这样定义:
repositories {
maven {
url 'https://dl.bintray.com/nuuneoi/maven/'
}
}
...
dependencies {
compile 'com.inthecheesefactory.thecheeselibrary:fb-like:0.9.3'
}
你可以从bintray网站界面上,找到你自己Maven仓库的url,也可以简单的用你的bintray用户名替换nuuneoi。我建议你进入网页,看看具体是怎么回事。
正如上面所提到的,让开发者定义这么复杂的配置,并非是发布library最好的方式,想象一下,如果要添加10个library,也需要添加10个url么?这简直是噩梦,所以,为了更好的使用,让我们把library从自己的仓库转移到jcenter。
Part 6 : 同步bintray上的用户仓库到jcenter
同步library到jcenter非常的简单,只需要打开网页点击Add to JCenter。
不需要其他额外操作,点击Send就可以了。
接下来我们什么也不需要做,等待两三个小时,让bintray团队通过我们的请求就可以了。一旦审核通过,你将会收到一封邮件,提示信息有改变。现在让我们回到网页,你可以看到在Linked To部分有所改变。
到现在为止,任何使用jcenter的开发者,只需要一行代码就可以使用我们的library了。
compile 'com.inthecheesefactory.thecheeselibrary:fb-like:0.9.3'
想要在jcenter上查看你的library文件?你可以通过访问http://jcenter.bintray.com,通过library的group id和artifact id来匹配浏览。在这个例子里,应该是:com -> inthecheesefactory -> thecheeselibrary -> fb-like -> 0.9.3。
请注意,链接到jcenter是一次性行为。到现在为止,如果你的包做了任何的修改,例如,上传了新版本的library,删掉了就版本等等。这些改变也会影响到jcenter。所以当你的仓库和jcenter存在差异的时候,你应该花2-3分钟同步这些改变到jcenter。
请注意,如果你决定删掉整个包,放置在jcenter仓库里面的library不会被删除,它们就像僵尸文件一样,没有人可以删除。所以我建议,如果你想要删掉整个包,在移除之前,请先从网站上删掉每一个单独的版本。
Part 7 : 上传library到Maven Central
不是所有的Android开发者都在使用jcenter。还是有一部分开发者在使用mavenCentral(),所以,让我们把library也上传到Maven Central。
为了把library从jcenter提交到Maven Central,有两个前提是需要满足的:
1)二进制包必须已经连接到jcenter
2)Maven Central上的仓库已经批准开放
如果你已经有了这些资格,那么提交library文件到Maven Central也是非常的简单。仅仅需要点击Maven Central连接到包的详细页面。
通过Sonatype的用户名和密码进入页面,点击Sync。
如果同步成功,将会显示最新的同步状态,如果失败,也会显示最新的同步失败信息。你必须解决这些问题,因为上传到Maven Central是非常严格的,比如“+”号不能用于版本库依赖关系的定义。
一旦完成,你可以在Maven Central Repository 找到自己的library文件,匹配规则同上,在这个例子中,应该是:com -> inthecheesefactory -> thecheeselibrary -> fb-like -> 0.9.3。
恭喜你,以上就是全部过程,这篇文章很长,但希望对你有用。