Android studio 发布Android Library项目到JCenter
Posted Ruffian-痞子
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android studio 发布Android Library项目到JCenter相关的知识,希望对你有一定的参考价值。
互联网的发展是非常迅猛的,刚刚觉得自己适应了eclipse的用法,突然发现它已经被淘汰了。
OK,今天不是来说eclipse和android studio的褒贬。我们是来学习技术的。在做SDK相关的开发时发现一个问题,Android studio 使用第三方包超级简单方便。一行代码搞定。
compile ‘com.ruffian.utils.android:utilssdk:0.1.0’
这就可以把第三包(Library)导入到项目编译使用。我的天啊,这么神奇吗?回想起使用eclipse导入项目,当做依赖包使用的艰辛,是不是顿时觉得这种方式碉堡了。
这行神奇的代码背后影藏着什么呢?先问问自己
1.首先这个第三方包如何能为我所用?它在哪里?云服务器?本地?
2.这个第三方包的项目结构怎样?jar?apk?
3.如何能做到,让别人一行代码使用我们的Library包?
1.首先这个第三方包如何能为我所用?它在哪里?云服务器?本地?
通过测试发现,这个第三方包,存在云服务器上,compile 之后Android studio 会将代码下载到本地。通过以下方式查看文件位置
项目右键->Library Properties 就可以查看文件位置
2.这个第三方包的项目结构怎样?jar?apk?
在Library文件目录项看到三个文件夹,里面分别有一个文件,后缀是
- .pom
- .jar
- .aar
.pom后缀的文件是什么?网上解释:
.pom:Project Object Model,在maven1中叫做project.xml,到maven2后改为pom.xml。该文件用于管理:源代码、配置文件、开发者的信息和角色、问题追踪系统、组织信息、项目授权、项目的url、项目的依赖关系等等。一个maven项目可以没有任何源代码,但必须包含pom文件。
打开 .pom 文件,可以看到是关于library项目的一些基本信息。(看来网上说的是真的)
.jar:不解释了,就是java/Android代码
.aar: 文件是啥?貌似听过,印象中,aar是 SDK的一种项目结构,使用studio打包。而我们使用eclipse处理SDK Library一般是一个完整的Android项目(包括资源文件)和jar文件,又听人说是属于Android的东西,还几乎只跟Android studio有关。网上是这么解释的:
(1) .aar:文件是在jar文件之上开发的。之所以有它是因为有些Android Library需要植入一些安卓特有的文件,比如AndroidManifest.xml,资源文件,Assets或者JNI。这些都不是jar文件的标准。
诶:这个好像说的通,当初刚开始做SDK开发的时候就是绞尽脑汁在想怎么解决Android资源文件打包的问题,代码打包成jar没问题,但是资源文件,和配置文件不行啊,看来aar的存在是合理的。网上还解释说:
(2) 因此aar文件就时发明出来包含所有这些东西的。总的来说它和jar一样只是普通的zip文件,不过具有不同的文件结构。jar文件以classes.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)
你说是就是啊,我不信呢,那么修改后缀为zip,并解压出来,看看里面什么状况
好像差不多是这样的哦,那就先这么认为吧。
3.如何能做到,让别人一行代码使用我们的Library包?
前面简单交代一下1,2两个问题。接下来说说我们一个普普通通的开发者如何做到看似高大上的行为。
其实Android Studio是从build.gradle里面定义的Maven 仓库服务器上下载library的。Apache Maven是Apache开发的一个工具,提供了用于贡献library的文件服务器。有两个标准的Android library文件服务器:jcenter 和 Maven Central。
jcenter 和 Maven Central
先了解一下这两个是什么东西
jcenter: jcenter是一个由 bintray.com维护的Maven仓库 。你可以在这里看到整个仓库的内容。
我们在项目的build.gradle 文件中如下定义仓库,就能使用jcenter了:
allprojects {
repositories {
jcenter()
}
}
Maven Central: Maven Central 则是由sonatype.org维护的Maven仓库。你可以在这里看到整个仓库。
注:不管是jcenter还是Maven Central ,两者都是Maven仓库
我们在项目的build.gradle 文件中如下定义仓库,就能使用Maven Centra
projects {
repositories {
mavenCentral()
}
}
注意,虽然jcenter和Maven Central 都是标准的 android library仓库,但是它们维护在完全不同的服务器上,由不同的人提供内容,两者之间毫无关系。在jcenter上有的可能 Maven Central 上没有,反之亦然。
除了两个标准的服务器之外,如果我们使用的library的作者是把该library放在自己的服务器上,我们还可以自己定义特有的Maven仓库服务器。Twitter的Fabric.io 就是这种情况,它们在https://maven.fabric.io/public上维护了一个自己的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 哪个好?
事实上两个仓库都具有相同的使命:提供Java或者Android 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上也极有可能有。换句话说jcenter是Maven Central的超集。
- 上传library到仓库很简单,不需要像在 Maven Central上做很多复杂的事情。
- 友好的用户界面
- 如果你想把library上传到 Maven Central ,你可以在bintray网站上直接点击一个按钮就能实现。
这么看起来好像jcenter更有优势一点,而且Android studio都将它作为默认的了,关键是它容易实现,好吧,那就把重心放在jcenter。
关于如何将Android Library发布到JCenter的操作可以查看下面这篇文章
https://inthecheesefactory.com/blog/how-to-upload-library-to-jcenter-maven-central-as-dependency/en
卧槽,这么坑爹,丢给你们一个英文网站就算完了?那好咯,给多一个中文的翻译
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0623/3097.html
这是一篇好文章,能看懂的话基本都知道怎么回事了,列举的条条是道,但是好像有点坑爹,怎么弄都跑不起来,或者各种报错。程序员嘛,谁跟你讲道理,跑起来才是硬道理。好吧,下面是我尝试了之后做了一下总结跟改进。反正我是成功实现了。我跑起来了,怎么样。
- 第1部分:在bintray上创建package
- 第2部分:准备一个Android Studio项目
- 第3部分:把library上传到你的bintray空间
- 第4部分:测试使用
第1部分:可以参考上面链接文章操作,注册账号,创建包名。图文并茂真的可以参考,就不在重复
第2部分:创建一个Android studio项目,然后添加一个module,做为library项目
2.1创建项目
2.2配置项目[ 这个是最关键的啦 ](跳过功能代码部分,可以写一个最简单的log类)
为了快速上手,这里直接给出几个配置文件的代码
1.在library模块中添加以下3个文件
1.1 project.properties
#project
project.name=UtilsSdk
project.groupId=com.ruffian.utils.android
project.artifactId=utilssdk
project.versionName=0.1.0
project.packaging=aar
#这两个值可以随便找一个项目
project.siteUrl=https://github.com/adamrocker/volley
project.gitUrl=https://github.com/adamrocker/volley.git
#javadoc
javadoc.name=UtilsSdk
解释一下文件(记得实际项目中一定要替换成开发者自己的项目名称,包名等等)
project.name:项目名称
project.groupId:项目组ID,通常情况下如果你的包名为com.example.test,那么项目组ID就是com.example
project.artifactId:项目ID,通常情况下如果你的包名为com.example.test,那么项目ID就是test
project.packaging:包类型,Android库是aar
project.siteUrl:项目官方网站的地址,没有的话就用Github上的地址,例如:https://github.com/adamrocker/volley
project.gitUrl:项目的Git地址,例如:https://github.com/adamrocker/volley.git
javadoc.name:生成的javadoc打开后主页显示的名称,通常跟项目名称一样即可
1.2 local.properties
#bintray
bintray.user=ruffian
bintray.apikey=******************
#developer
developer.id=Ruffian
developer.name=RuffianZhong
developer.email=RuffianZhong@gmail.com
解释一下文件(记得实际项目中一定要替换成开发者自己的项目名称,包名等等)
bintray.user:你的Bintray的用户名
bintray.apikey:你的的Bintray的API Key
developer.id:通常是你在开源社区的昵称
developer.name:你的姓名
developer.email:你的邮箱
1.3 bintrayUpload.gradle
apply plugin: 'com.github.dcendents.android-maven'
apply plugin: 'com.jfrog.bintray'
// load properties
Properties properties = new Properties()
File localPropertiesFile = project.file("local.properties");
if (localPropertiesFile.exists()) {
properties.load(localPropertiesFile.newDataInputStream())
}
File projectPropertiesFile = project.file("project.properties");
if (projectPropertiesFile.exists()) {
properties.load(projectPropertiesFile.newDataInputStream())
}
// read properties
def projectName = properties.getProperty("project.name")
def projectGroupId = properties.getProperty("project.groupId")
def projectArtifactId = properties.getProperty("project.artifactId")
def projectVersionName = properties.getProperty("project.versionName")
def projectPackaging = properties.getProperty("project.packaging")
def projectSiteUrl = properties.getProperty("project.siteUrl")
def projectGitUrl = properties.getProperty("project.gitUrl")
def developerId = properties.getProperty("developer.id")
def developerName = properties.getProperty("developer.name")
def developerEmail = properties.getProperty("developer.email")
def bintrayUser = properties.getProperty("bintray.user")
def bintrayApikey = properties.getProperty("bintray.apikey")
def javadocName = properties.getProperty("javadoc.name")
group = projectGroupId
// This generates POM.xml with proper parameters
install {
repositories.mavenInstaller {
pom {
project {
name projectName
groupId projectGroupId
artifactId projectArtifactId
version projectVersionName
packaging projectPackaging
url projectSiteUrl
licenses {
license {
name 'The Apache Software License, Version 2.0'
url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
}
}
developers {
developer {
id developerId
name developerName
email developerEmail
}
}
scm {
connection projectGitUrl
developerConnection projectGitUrl
url projectSiteUrl
}
}
}
}
}
// This generates sources.jar
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))
}
// This generates javadoc.jar
task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
}
artifacts {
archives javadocJar
archives sourcesJar
}
// javadoc configuration
javadoc {
options {
encoding "UTF-8"
charSet 'UTF-8'
author true
version projectVersionName
links "http://docs.oracle.com/javase/7/docs/api"
title javadocName
}
}
// bintray configuration
bintray {
user = bintrayUser
key = bintrayApikey
configurations = ['archives']
pkg {
repo = "maven"
name = projectName
websiteUrl = projectSiteUrl
vcsUrl = projectGitUrl
licenses = ["Apache-2.0"]
publish = true
}
}
bintrayUpload.gradle这个文件不用解释,不用修改,直接复制
2.在library目录下的build.gradle文件 最后一行 添加代码
apply from: "bintrayUpload.gradle"
引用本地的 “bintrayUpload.gradle” 文件。这个文件的代码直接复制到项目中即可,不需要修改。
3.在项目目录下的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'
}
解释一下
android-maven-gradle-plugin插件是用来打包Maven所需文件的
gradle-bintray-plugin插件是用来将生成的Maven所需文件上传到Bintray的
好了,精华都在那几个配置文件里面了,前提是在bintray上面已经建好了账号。填好包名
接下来就要上传代码到bintray中了。
第3部分:把library上传到你的bintray空间
3.1请到Android Studio的终端(Terminal)选项卡
第一步是检查代码的正确性,以及编译library文件(aar,pom等等),输入下面的命令:
gradlew install
如果没有什么问题,会显示:
BUILD SUCCESSFUL
现在我们已经成功一半了。下一步是上传编译的文件到bintray,使用如下的命令:
gradlew bintrayUpload
如果显示如下你就大声问问周围的人:“你看我吊不!”,然后去在bintray的网页上检查一下你的package
SUCCESSFUL
但是你怎么可能有我那么吊,你肯定一直在报错,哈哈。报错就对了。
常见问题
Error:Cause: org/gradle/api/publication/maven/internal/DefaultMavenFactory
这时候你只需将android-maven-gradle-plugin 插件版本改为
classpath ‘com.github.dcendents:android-maven-gradle-plugin:1.3’ 即可
—我是分隔符—
You are using JDK version ‘java version “1.7.0_71”’. Some versions of JDK 1.7 (e.g. 1.7.0_10) may cause class loading errors in Gradle.Please update to a newer version (e.g. 1.7.0_67)
同样的你只需要将android-maven-gradle-plugin 插件版本改为
classpath ‘com.github.dcendents:android-maven-gradle-plugin:1.3’ 即可
—我是分隔符—
No value has been specified for property ‘packageName’.
出这个问题肯定是看文档不仔细,把project.properties文件放在了项目根目录下,一定要放在mudule目录下才可以
—我是分隔符—
Could not upload to ‘https://.pom’: HTTP/1.1 400 Bad Request [message:Unable to upload files: Maven group, artifact or version defined in the pom file do not match the file path ‘***.pom’]
这个问题一般都是你的module的名字和你在project.properties 配置的artifactId不一致导致的,改成一样的即可
估计这几个问题之后就应该可以看见SUCCESS了。现在看看bintray网站上面的变化
1.
2.
3.
终于把代码放到了网上,现在需要将代码从bintray同步到jcenter。这一步很简单,查看链接中的文章有说明。
那现在是不是就可以实现1行代码实现吊炸天的操作?哪有那么容易,随便弄一下就想一行代码搞定?
得2行代码!!
因为代码从bintray同步到jcenter需要几个小时的时间,但是我已经等不及想看看自己成果,那么就多写一行代码配置一下library路径就可以了
新建一个Android studio 测试项目。
在项目根目录下的build.gradle中添加,因为项目还没有发布到jcenter,相当于现在是在自己的服务器维护这个library
allprojects {
repositories {
jcenter(){
//开发者bintray的路径,当项目发布到jcenter之后就可以去除这行代码
url 'https://dl.bintray.com/ruffian/maven/'
}
}
}
引入Library项目,在APP目录下的build.gradle中添加
dependencies {
//utils
compile 'com.ruffian.utils.android:utilssdk:0.1.0'
}
sync now
ok,搞定,在activity中调用Library中的方法测试一下,能正确调用。没问题!你做到了
备注:文章中有些想法来自网络,一时间找不到原文链接,还望原作者见谅
有什么问题可以留言讨论,共同进步
以上是关于Android studio 发布Android Library项目到JCenter的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Android Studio 在发布模式下调试 Android App
如何发布 Android .aar 源码让 Android Studio 自动找到它们?
Android Studio 将项目从 Eclipse 导入 Android Studio