Android studio 发布Android Library项目到JCenter

来源:互联网 发布:程序员项目介绍范文 编辑:程序博客网 时间:2024/05/22 02:13

(本来这篇文章只是想当做笔记记录,下了班才写的,第二天起来看到几百个访问量,突然对生活充满了希望,受到了鼓舞,于是决定完善一下。____2016/05/31)

互联网的发展是非常迅猛的,刚刚觉得自己适应了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文件目录项看到三个文件夹,里面分别有一个文件,后缀是

  1. .pom
  2. .jar
  3. .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. 第1部分:在bintray上创建package
  2. 第2部分:准备一个Android Studio项目
  3. 第3部分:把library上传到你的bintray空间
  4. 第4部分:测试使用

第1部分:可以参考上面链接文章操作,注册账号,创建包名。图文并茂真的可以参考,就不在重复

第2部分:创建一个Android studio项目,然后添加一个module,做为library项目

2.1创建项目

这里写图片描述

2.2配置项目[ 这个是最关键的啦 ](跳过功能代码部分,可以写一个最简单的log类)

为了快速上手,这里直接给出几个配置文件的代码
1.在library模块中添加以下3个文件
1.1 project.properties

#projectproject.name=UtilsSdkproject.groupId=com.ruffian.utils.androidproject.artifactId=utilssdkproject.versionName=0.1.0project.packaging=aar#这两个值可以随便找一个项目project.siteUrl=https://github.com/adamrocker/volleyproject.gitUrl=https://github.com/adamrocker/volley.git#javadocjavadoc.name=UtilsSdk

解释一下文件(记得实际项目中一定要替换成开发者自己的项目名称,包名等等)

project.name:项目名称project.groupId:项目组ID,通常情况下如果你的包名为com.example.test,那么项目组ID就是com.exampleproject.artifactId:项目ID,通常情况下如果你的包名为com.example.test,那么项目ID就是testproject.packaging:包类型,Android库是aarproject.siteUrl:项目官方网站的地址,没有的话就用Github上的地址,例如:https://github.com/adamrocker/volleyproject.gitUrl:项目的Git地址,例如:https://github.com/adamrocker/volley.gitjavadoc.name:生成的javadoc打开后主页显示的名称,通常跟项目名称一样即可

1.2 local.properties

#bintraybintray.user=ruffianbintray.apikey=******************#developerdeveloper.id=Ruffiandeveloper.name=RuffianZhongdeveloper.email=RuffianZhong@gmail.com

解释一下文件(记得实际项目中一定要替换成开发者自己的项目名称,包名等等)

bintray.user:你的Bintray的用户名bintray.apikey:你的的Bintray的API Keydeveloper.id:通常是你在开源社区的昵称developer.name:你的姓名developer.email:你的邮箱

1.3 bintrayUpload.gradle

apply plugin: 'com.github.dcendents.android-maven'apply plugin: 'com.jfrog.bintray'// load propertiesProperties 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 propertiesdef 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 parametersinstall {    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.jartask 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.jartask javadocJar(type: Jar, dependsOn: javadoc) {    classifier = 'javadoc'    from javadoc.destinationDir}artifacts {    archives javadocJar    archives sourcesJar}// javadoc configurationjavadoc {    options {        encoding "UTF-8"        charSet 'UTF-8'        author true        version projectVersionName        links "http://docs.oracle.com/javase/7/docs/api"        title javadocName    }}// bintray configurationbintray {    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中的方法测试一下,能正确调用。没问题!你做到了

备注:文章中有些想法来自网络,一时间找不到原文链接,还望原作者见谅

有什么问题可以留言讨论,共同进步

2 0
原创粉丝点击