13518219792

建站动态

根据您的个性需求进行定制 先人一步 抢占小程序红利时代

创建和发布Android开发库的终极指南

我经常被 Android 开发社区中如此多而且好用的第三方库所震惊。有很长的一段时间,我想贡献一些东西,但我不知道如何去做。在浏览了其他很多关于如何发布一个 android 开发库的文章后,我仍然发现缺失了一些细节,而且,所有的信息都是在不同的地方。所以,我将完整的走过这个过程,向大家展示我的做法。

创新互联公司是一家专注于网站建设、做网站绵阳主机托管的网络公司,有着丰富的建站经验和案例。

对新手来说,我推荐使用 Android Studio 来创建所有的 Android 项目,Android Studio官方使用 Gradle 构建系统。请确保你下载了 Android Studio 的最新版。

相关术语介绍

在我们开始之前,还有一些术语,需要熟悉下。

项目(Project) — 在 Android Studio 中,一个 项目 就是一个完整的 Android app。Android Studio 项目包含了一个或多个模块。 在 Android Studio 中,一个 项目 类似于在 Eclipse 的一个工作区间( workspace )。

模块( Module) – 一个 模块 是 app 中的一个组件,它可以单独的进行构建、测试和调试。模块包含了 app 的源代码和资源文件。在 Android Studio 中,一个 模块 类似于在 Eclipse 的一个项目。

AAR – ‘aar’ 套件是 Android 开发库项目的二进制的分发形式。(AAR 格式)开发库项目的主要产出就是 .aar 包(意思是 Android 压缩包)。它是由编译后的代码(如 jar 文件或者 .so 文件)和资源文件(如 manifest 文件、res 文件、asset 文件)组合而成的。

Maven 中央仓库 – 由 Maven 社区提供的仓库。它包含了很多我们常用的开发库。 Search Maven 网站可用来浏览 maven 中央仓库的内容。Gradle, Please 网站是另一个可用来搜索中央仓库的工具。如果你在项目配置文件的仓库配置部分添加了 jCenter() ,那么 Gradle 将使用 jCenter 仓库( jCenter 的说明)。Maven 中央仓库也经常被称作 Maven 中心或者中央仓库。

Sonatype — Sonatype的开源软件仓库托管(OSSRH)服务是项目作者和贡献者们发布他们的组件到中央仓库的主要途径。它是 Sonatype Nexus Professional 组织利用 Nexus Staging Suite 工具,对开源项目提供部署托管服务,该服务主要用来处理部署和验证操作,也提供同步操作将内容通过网络投递到中央仓库。

GPG – GNU 隐私保护组织 (也称为 GPG 或者 GnuPG),这个 GNU 项目是一个加密软件,遵循 OpenPGP (RFC4880)标准,是 PGP 的免费替代品。使用 GPG 你可以加密(解密)包含敏感数据的文件,比如那些由健康保险携带和责任法案 (HIPAA) 制定的受保护的隐私和安全方面的电子健康信息。想了解 GPG 的更多信息,请访问 GNU Privacy Guard website。

准备好你的 Android 开发库

我将使用我的 Trestle 开发库作例子来讲解。在你的项目中,需要修改一些地方,来准备作为一个开发库发布到 Maven 中央仓库中。

 
 
 
 
  1. apply plugin: 'com.android.application' 
  2.  
  3. dependencies { 
  4.  
  5.     compile project(':library') 
  6. }  
 
 
 
 
  1. apply plugin: 'com.android.library' 
  2.  
  3. apply from: 'maven-push.gradle'  
 
 
 
 
  1. POM_NAME=ProjectName 
  2.  
  3. POM_ARTIFACT_ID=projectname 
  4.  
  5. POM_PACKAGING=aar  
 
 
 
 
  1. /* 
  2.  
  3. * Copyright 2013 Chris Banes 
  4.  
  5.  
  6. * Licensed under the Apache License, Version 2.0 (the "License"); 
  7.  
  8. * you may not use this file except in compliance with the License. 
  9.  
  10. * You may obtain a copy of the License at 
  11.  
  12.  
  13. *     http://www.apache.org/licenses/LICENSE-2.0 
  14.  
  15.  
  16. * Unless required by applicable law or agreed to in writing, software 
  17.  
  18. * distributed under the License is distributed on an "AS IS" BASIS, 
  19.  
  20. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  21.  
  22. * See the License for the specific language governing permissions and 
  23.  
  24. * limitations under the License. 
  25.  
  26. */ 
  27.  
  28.   
  29.  
  30. apply plugin: 'maven' 
  31.  
  32. apply plugin: 'signing' 
  33.  
  34.   
  35.  
  36. def isReleaseBuild() { 
  37.  
  38.     return VERSION_NAME.contains("SNAPSHOT") == false 
  39.  
  40.  
  41.   
  42.  
  43. def getReleaseRepositoryUrl() { 
  44.  
  45.     return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL 
  46.  
  47.             : "https://oss.sonatype.org/service/local/staging/deploy/maven2/" 
  48.  
  49.  
  50.   
  51.  
  52. def getSnapshotRepositoryUrl() { 
  53.  
  54.     return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL 
  55.  
  56.             : "https://oss.sonatype.org/content/repositories/snapshots/" 
  57.  
  58.  
  59.   
  60.  
  61. def getRepositoryUsername() { 
  62.  
  63.     return hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : "" 
  64.  
  65.  
  66.   
  67.  
  68. def getRepositoryPassword() { 
  69.  
  70.     return hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : "" 
  71.  
  72.  
  73.   
  74.  
  75. afterEvaluate { project -> 
  76.  
  77.     uploadArchives { 
  78.  
  79.         repositories { 
  80.  
  81.             mavenDeployer { 
  82.  
  83.                 beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } 
  84.  
  85.   
  86.  
  87.                 pom.groupId = GROUP 
  88.  
  89.                 pom.artifactId = POM_ARTIFACT_ID 
  90.  
  91.                 pom.version = VERSION_NAME 
  92.  
  93.   
  94.  
  95.                 repository(url: getReleaseRepositoryUrl()) { 
  96.  
  97.                     authentication(userName: getRepositoryUsername(), password: getRepositoryPassword()) 
  98.  
  99.                 } 
  100.  
  101.                 snapshotRepository(url: getSnapshotRepositoryUrl()) { 
  102.  
  103.                     authentication(userName: getRepositoryUsername(), password: getRepositoryPassword()) 
  104.  
  105.                 } 
  106.  
  107.   
  108.  
  109.                 pom.project { 
  110.  
  111.                     name POM_NAME 
  112.  
  113.                     packaging POM_PACKAGING 
  114.  
  115.                     description POM_DESCRIPTION 
  116.  
  117.                     url POM_URL 
  118.  
  119.   
  120.  
  121.                     scm { 
  122.  
  123.                         url POM_SCM_URL 
  124.  
  125.                         connection POM_SCM_CONNECTION 
  126.  
  127.                         developerConnection POM_SCM_DEV_CONNECTION 
  128.  
  129.                     } 
  130.  
  131.   
  132.  
  133.                     licenses { 
  134.  
  135.                         license { 
  136.  
  137.                             name POM_LICENCE_NAME 
  138.  
  139.                             url POM_LICENCE_URL 
  140.  
  141.                             distribution POM_LICENCE_DIST 
  142.  
  143.                         } 
  144.  
  145.                     } 
  146.  
  147.   
  148.  
  149.                     developers { 
  150.  
  151.                         developer { 
  152.  
  153.                             id POM_DEVELOPER_ID 
  154.  
  155.                             name POM_DEVELOPER_NAME 
  156.  
  157.                         } 
  158.  
  159.                     } 
  160.  
  161.                 } 
  162.  
  163.             } 
  164.  
  165.         } 
  166.  
  167.     } 
  168.  
  169.   
  170.  
  171.     signing { 
  172.  
  173.         required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") } 
  174.  
  175.         sign configurations.archives 
  176.  
  177.     } 
  178.  
  179.   
  180.  
  181.     //task androidJavadocs(type: Javadoc) { 
  182.  
  183.     //source = android.sourceSets.main.allJava 
  184.  
  185.     //} 
  186.  
  187.   
  188.  
  189.     //task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) { 
  190.  
  191.     //classifier = 'javadoc' 
  192.  
  193.     //from androidJavadocs.destinationDir 
  194.  
  195.     //} 
  196.  
  197.   
  198.  
  199.     task androidSourcesJar(type: Jar) { 
  200.  
  201.         classifier = 'sources' 
  202.  
  203.         from android.sourceSets.main.java.sourceFiles 
  204.  
  205.     } 
  206.  
  207.   
  208.  
  209.     artifacts { 
  210.  
  211.         archives androidSourcesJar 
  212.  
  213.     } 
  214.  
  215. }  
 
 
 
 
  1. # [Android] ======================== 
  2.  
  3. # Built application files 
  4.  
  5. *.apk 
  6.  
  7. *.ap_ 
  8.  
  9.   
  10.  
  11. # Files for the Dalvik VM 
  12.  
  13. *.dex 
  14.  
  15.   
  16.  
  17. # Java class files 
  18.  
  19. *.class 
  20.  
  21.   
  22.  
  23. # Generated files 
  24.  
  25. bin/ 
  26.  
  27. gen/ 
  28.  
  29.   
  30.  
  31. # Gradle files 
  32.  
  33. .gradle/ 
  34.  
  35. build/ 
  36.  
  37.   
  38.  
  39. # Local configuration file (sdk path, etc) 
  40.  
  41. local.properties 
  42.  
  43.   
  44.  
  45. # Proguard folder generated by Eclipse 
  46.  
  47. proguard/ 
  48.  
  49.   
  50.  
  51. # Log Files 
  52.  
  53. *.log 
  54.  
  55.   
  56.  
  57. ## Directory-based project format: 
  58.  
  59. .idea/ 
  60.  
  61.   
  62.  
  63. ## File-based project format: 
  64.  
  65. *.ipr 
  66.  
  67. *.iws 
  68.  
  69.   
  70.  
  71. ## Plugin-specific files: 
  72.  
  73.   
  74.  
  75. # IntelliJ 
  76.  
  77. out/ 
  78.  
  79.   
  80.  
  81. # mpeltonen/sbt-idea plugin 
  82.  
  83. .idea_modules/ 
  84.  
  85.   
  86.  
  87. # JIRA plugin 
  88.  
  89. atlassian-ide-plugin.xml 
  90.  
  91.   
  92.  
  93. # Crashlytics plugin (for Android Studio and IntelliJ) 
  94.  
  95. com_crashlytics_export_strings.xml 
  96.  
  97.   
  98.  
  99. # [Maven] ======================== 
  100.  
  101. target/ 
  102.  
  103. pom.xml.tag 
  104.  
  105. pom.xml.releaseBackup 
  106.  
  107. pom.xml.versionsBackup 
  108.  
  109. pom.xml.next 
  110.  
  111. release.properties 
  112.  
  113.   
  114.  
  115. # [Gradle-Android] ======================== 
  116.  
  117.   
  118.  
  119. # Ignore Gradle GUI config 
  120.  
  121. gradle-app.setting 
  122.  
  123.   
  124.  
  125. # Gradle Signing 
  126.  
  127. signing.properties 
  128.  
  129. trestle.keystore 
  130.  
  131.   
  132.  
  133. # Mobile Tools for Java (J2ME) 
  134.  
  135. .mtj.tmp/ 
  136.  
  137.   
  138.  
  139. # Package Files # 
  140.  
  141. *.jar 
  142.  
  143. *.war 
  144.  
  145. *.ear 
  146.  
  147.   
  148.  
  149. # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 
  150.  
  151. hs_err_pid* 
  152.  
  153.   
  154.  
  155. # Misc 
  156.  
  157. /.idea/workspace.xml 
  158.  
  159. .DS_Store 
  160.  
  161. /captures 
  162.  
  163. **/*.iml 
  164.  
  165. *.class  
 
 
 
 
  1. include ':sample', ':library' 
 
 
 
 
  1. # Project-wide Gradle settings. 
  2.  
  3.   
  4.  
  5. # IDE (e.g. Android Studio) users: 
  6.  
  7. # Gradle settings configured through the IDE *will override* 
  8.  
  9. # any settings specified in this file. 
  10.  
  11.   
  12.  
  13. # For more details on how to configure your build environment visit 
  14.  
  15. # http://www.gradle.org/docs/current/userguide/build_environment.html 
  16.  
  17.   
  18.  
  19. # Specifies the JVM arguments used for the daemon process. 
  20.  
  21. # The setting is particularly useful for tweaking memory settings. 
  22.  
  23. # Default value: -Xmx10248m -XX:MaxPermSize=256m 
  24.  
  25. # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 
  26.  
  27.   
  28.  
  29. # When configured, Gradle will run in incubating parallel mode. 
  30.  
  31. # This option should only be used with decoupled projects. More details, visit 
  32.  
  33. # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 
  34.  
  35. # org.gradle.parallel=true 
  36.  
  37.   
  38.  
  39. VERSION_NAME=0.0.1 
  40.  
  41. VERSION_CODE=1 
  42.  
  43. GROUP=com.github.github_username 
  44.  
  45.   
  46.  
  47. POM_DESCRIPTION=A library that does X, Y, and Z 
  48.  
  49. POM_URL=https://github.com/github_username/ProjectName 
  50.  
  51. POM_SCM_URL=https://github.com/github_username/ProjectName 
  52.  
  53. POM_SCM_CONNECTION=scm:git@github.com:github_username/ProjectName.git 
  54.  
  55. POM_SCM_DEV_CONNECTION=scm:git@github.com:github_username/ProjectName.git 
  56.  
  57. POM_LICENCE_NAME=The Apache Software License, Version 2.0 
  58.  
  59. POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt 
  60.  
  61. POM_LICENCE_DIST=repo 
  62.  
  63. POM_DEVELOPER_ID=github_username 
  64.  
  65. POM_DEVELOPER_NAME=GitHub FullName  

安装 GPG

如果你的机器上还没安装 GPG,你需要下载安装它。如果你是 MacOSX 系统,安装手册在这里。

如果你从未使用过 GPG – 首先,请创建 GPG 密钥:

 
 
 
 
  1. $ gpg --gen-key 

在你创建 GPG 密钥的时候,如果你不确定该如何回答问题, 这篇指南(Creating an encryption key)可以帮上忙。

接下来,找到你的密钥 ID:

 
 
 
 
  1. $ gpg --list-keys 

第一行像是 pub XXXXX/YYYYYYYY <日期>的。切记,’YYYYYYYY’ 部分,就是你的密钥 ID。

现在,发布你的密钥:

 
 
 
 
  1. $ gpg --keyserver hkp://keyserver.ubuntu.com --send-keys YYYYYYYY 
  2.  
  3. $ gpg --keyserver hkp://pgp.mit.edu --send-keys YYYYYYYY  

你当然也可以使用其他密钥服务器,你也可以通过如下命令确认你的密钥是否已经发布:

 
 
 
 
  1. $ gpg --keyserver hkp://pgp.mit.edu --search-keys johndoe@example.com # 使用你的邮箱 

为了使你的开发库在 Gradle, Please网站上列出(也为了其他人方便的引用你的开发库),请上传你的项目到 Maven Central。 最简单的上传项目的方法是使用 Sonatype。

Sonatype

  1. 在Sonatype 创建一个 JIRA 帐号。
  2. 登录成功后,创建一个 new issue。   

我为我的 Trestle 项目创建了一个 GitHub 仓库。所以我在 new issue 上填写的字段大概如此:

Group Id : com.github.

Project URL : https://github.com//

SCM url : https://github.com//.git

Username :

Already Synced to Central : No

注意:我在你需要填写的字段上增加了括号作为占位符。你需要将它们替换成合适的值。

当你准备提交 issue 的时候,issue 的细节应该要和上面的截图差不多。当你提交完成后,Sonatype 将用 2 个工作日来处理你的 issue。接着,你将收到一份确认邮件,告知你的配置已经准备好了,你可以发布你的开源库了。

不要部署你的开源库,直到你接收到一封表明你的票据已经 OK 了的邮件。 对新项目来说,一个通病就是过早的部署。这将会误使你的构件(artifacts)变成一个人人都能获得的仓库。

最后,如果你的组件已经在中央仓库中了,请在你的票据中添加以下信息,并参考这篇文章,如何迁移到 OSSRH。

修改你本机上的 ~/.gradle/gradle.properties 文件,包含以下内容:

 
 
 
 
  1. NEXUS_USERNAME=sonatype_username 
  2.  
  3. NEXUS_PASSWORD=sonatype_password 
  4.  
  5. signing.keyId=gpg_key_id 
  6.  
  7. signing.password=gpg_password 
  8.  
  9. signing.secretKeyRingFile=/Users/username/.gnupg/secring.gpg 
  10.  
  11. org.gradle.daemon=true  

当你发布开发库的时候,身份认证信息已经在 gradle.properties 文件中提供了。请确保提供了正确的 nexus 用户名和密码(也就是 Sonatype 的用户名和密码),否则你将得到未授权的 401 错误。

注意:如果你之前已经发布过一个开发库,那么你不需要在 JIRA(Sonatype) 上创建一个新的 issue。每个顶级的 groupId 对应一个 JIRA issue。你应该已经有了部署任何新构件到你的 groupId 或者下属 group 应需要的所有权限。中央仓库的同步操作遵循从上到下的过程,所以任何下属组的发布版本都将会自动同步。当你发布新组件,你不需要告诉 Sonatype,因为当你进行仓库同步工作的时候,没有什么需要 Sonatype 去配置或者检查的, Sonatype 仅仅会在第一次进行同步操作的时候,发布一条 twitter。

发布

一旦你准备发布你的开发库,在 Android Studio 中, 打开右侧的 Gradle 视图,在 Tasks > upload 下,点击 uploadArchives,将会上传你的开发库到 Sonatype Staging Repositories。

在 Sonatype Staging Repositories 网页上,登陆你的 Sonatype 账号,查找你的 “staging” 开发库,它应该在列表的最后,选中它,并按下 “关闭” 按钮。关闭一个开发库实际上意味着你准备发布它。如果关闭操作一切顺利 – 你应该会看到一个激活了的 ‘发布’ 按钮。你可能需要刷新下页面。请按下发布按钮。请阅读关于使用 Nexus 管理仓库的帮助文档。如果这是你发布的第一个开发库,返回到 JIRA,在 JIRA 上发表一条你已经改进了你的开发库的评论,如果不是第一个,就没必要告诉 Sonatype 你改进了你的开发库。然后,你应该会收到来自 Sonatype 的一条回复信息,信息上说你的开发库在 10 分钟内能准备好,将会在接下来的几个小时同步到 Maven 中央仓库。几个小时之后,它将展示在 Gradle, Please 网站上。

使用你的开发库

对其他开发者来说,想要使用你的开发库,他们需要在 Android 项目的 build.gradle 文件中添加一条依赖, 如下所示:

 
 
 
 
  1. apply plugin: 'android' 
  2.  
  3. dependencies { 
  4.  
  5.     compile 'com.github.lawloretienne:trestle:0.0.3' 
  6.  

特别感谢

非常感谢 Chris Banes,Jonathan Le,Serge Zaitsev 以及其他发表博客的人们,你们的文章帮助我得以走过这个复杂的过程。

我的开发库

QuickReturn — https://github.com/lawloretienne/QuickReturn

Trestle — https://github.com/lawloretienne/Trestle

ImageGallery — https://github.com/lawloretienne/ImageGallery


文章题目:创建和发布Android开发库的终极指南
网站路径:http://cdbrznjsb.com/article/djhiojp.html

其他资讯

让你的专属顾问为你服务